From f6720271cb7f58084695e9cff2a9f3b3640b4525 Mon Sep 17 00:00:00 2001 From: Yingying Wang Date: Fri, 15 May 2020 12:20:31 -0700 Subject: [PATCH 01/62] sparce accessor exporter --- code/AssetLib/glTF2/glTF2Asset.h | 24 ++++ code/AssetLib/glTF2/glTF2Asset.inl | 130 ++++++++++++++++++- code/AssetLib/glTF2/glTF2AssetWriter.inl | 48 +++++-- code/AssetLib/glTF2/glTF2Exporter.cpp | 156 ++++++++++++++++++++++- 4 files changed, 346 insertions(+), 12 deletions(-) diff --git a/code/AssetLib/glTF2/glTF2Asset.h b/code/AssetLib/glTF2/glTF2Asset.h index 48dab24a7..a60ac98f3 100644 --- a/code/AssetLib/glTF2/glTF2Asset.h +++ b/code/AssetLib/glTF2/glTF2Asset.h @@ -367,6 +367,7 @@ struct Object { //! An accessor provides a typed view into a BufferView or a subset of a BufferView //! similar to how WebGL's vertexAttribPointer() defines an attribute in a buffer. struct Accessor : public Object { + struct Sparse; //wangyi 0506 Ref bufferView; //!< The ID of the bufferView. (required) size_t byteOffset; //!< The offset relative to the start of the bufferView in bytes. (required) ComponentType componentType; //!< The datatype of components in the attribute. (required) @@ -374,6 +375,7 @@ struct Accessor : public Object { AttribType::Value type; //!< Specifies if the attribute is a scalar, vector, or matrix. (required) std::vector max; //!< Maximum value of each component in this attribute. std::vector min; //!< Minimum value of each component in this attribute. + std::unique_ptr sparse; //wangyi 0506 unsigned int GetNumComponents(); unsigned int GetBytesPerComponent(); @@ -385,6 +387,10 @@ struct Accessor : public Object { void ExtractData(T *&outData); void WriteData(size_t count, const void *src_buffer, size_t src_stride); + //wangyi 0506 + void WriteSparseValues(size_t count, const void *src_data, size_t src_dataStride); + void WriteSparseIndices(size_t count, const void *src_idx, size_t src_idxStride); + //! Helper class to iterate the data class Indexer { @@ -423,6 +429,22 @@ struct Accessor : public Object { Accessor() {} void Read(Value &obj, Asset &r); + + //wangyi 0506 + //sparse + struct Sparse { + size_t count; + ComponentType indicesType; + Ref indices; + size_t indicesByteOffset; + Ref values; + size_t valuesByteOffset; + + std::vector data; //!< Actual data, which may be defaulted to an array of zeros or the original data, with the sparse buffer view applied on top of it. + + void PopulateData(size_t numBytes, uint8_t *bytes); + void PatchData(unsigned int elementSize); + }; }; //! A buffer points to binary geometry, animation, or skins. @@ -555,6 +577,8 @@ struct BufferView : public Object { BufferViewTarget target; //! The target that the WebGL buffer should be bound to. void Read(Value &obj, Asset &r); + //wangyi 0506 + uint8_t *GetPointer(size_t accOffset); }; struct Camera : public Object { diff --git a/code/AssetLib/glTF2/glTF2Asset.inl b/code/AssetLib/glTF2/glTF2Asset.inl index 881fd4efc..09fd48761 100644 --- a/code/AssetLib/glTF2/glTF2Asset.inl +++ b/code/AssetLib/glTF2/glTF2Asset.inl @@ -550,10 +550,67 @@ inline void BufferView::Read(Value &obj, Asset &r) { byteStride = MemberOrDefault(obj, "byteStride", 0u); } +//wangyi 0506 +inline uint8_t *BufferView::GetPointer(size_t accOffset) { + if (!buffer) return 0; + uint8_t *basePtr = buffer->GetPointer(); + if (!basePtr) return 0; + + size_t offset = accOffset + byteOffset; + if (buffer->EncodedRegion_Current != nullptr) { + const size_t begin = buffer->EncodedRegion_Current->Offset; + const size_t end = begin + buffer->EncodedRegion_Current->DecodedData_Length; + if ((offset >= begin) && (offset < end)) + return &buffer->EncodedRegion_Current->DecodedData[offset - begin]; + } + + return basePtr + offset; +} + // // struct Accessor // +//wangyi 0506 +inline void Accessor::Sparse::PopulateData(size_t numBytes, uint8_t *bytes) { + if (bytes) { + data.assign(bytes, bytes + numBytes); + } else { + data.resize(numBytes, 0x00); + } +} + +inline void Accessor::Sparse::PatchData(unsigned int elementSize) { + uint8_t *pIndices = indices->GetPointer(indicesByteOffset); + const unsigned int indexSize = int(ComponentTypeSize(indicesType)); + uint8_t *indicesEnd = pIndices + count * indexSize; + + uint8_t *pValues = values->GetPointer(valuesByteOffset); + while (pIndices != indicesEnd) { + size_t offset; + switch (indicesType) { + case ComponentType_UNSIGNED_BYTE: + offset = *pIndices; + break; + case ComponentType_UNSIGNED_SHORT: + offset = *reinterpret_cast(pIndices); + break; + case ComponentType_UNSIGNED_INT: + offset = *reinterpret_cast(pIndices); + break; + default: + // have fun with float and negative values from signed types as indices. + throw DeadlyImportError("Unsupported component type in index."); + } + + offset *= elementSize; + std::memcpy(data.data() + offset, pValues, elementSize); + + pValues += elementSize; + pIndices += indexSize; + } +} +// wangyi 0506 inline void Accessor::Read(Value &obj, Asset &r) { if (Value *bufferViewVal = FindUInt(obj, "bufferView")) { @@ -566,6 +623,43 @@ inline void Accessor::Read(Value &obj, Asset &r) { const char *typestr; type = ReadMember(obj, "type", typestr) ? AttribType::FromString(typestr) : AttribType::SCALAR; + + //wangyi 0506 + if (Value *sparseValue = FindObject(obj, "sparse")) { + sparse.reset(new Sparse); + // count + ReadMember(*sparseValue, "count", sparse->count); + + // indices + if (Value *indicesValue = FindObject(*sparseValue, "indices")) { + //indices bufferView + Value *indiceViewID = FindUInt(*indicesValue, "bufferView"); + sparse->indices = r.bufferViews.Retrieve(indiceViewID->GetUint()); + //indices byteOffset + sparse->indicesByteOffset = MemberOrDefault(*indicesValue, "byteOffset", size_t(0)); + //indices componentType + sparse->indicesType = MemberOrDefault(*indicesValue, "componentType", ComponentType_BYTE); + //sparse->indices->Read(*indicesValue, r); + } + + // value + if (Value *valuesValue = FindObject(*sparseValue, "values")) { + //value bufferView + Value *valueViewID = FindUInt(*valuesValue, "bufferView"); + sparse->values = r.bufferViews.Retrieve(valueViewID->GetUint()); + //value byteOffset + sparse->valuesByteOffset = MemberOrDefault(*valuesValue, "byteOffset", size_t(0)); + //sparse->values->Read(*valuesValue, r); + } + + // indicesType + sparse->indicesType = MemberOrDefault(*sparseValue, "componentType", ComponentType_UNSIGNED_SHORT); + + const unsigned int elementSize = GetElementSize(); + const size_t dataSize = count * elementSize; + sparse->PopulateData(dataSize, bufferView ? bufferView->GetPointer(byteOffset) : 0); + sparse->PatchData(elementSize); + } } inline unsigned int Accessor::GetNumComponents() { @@ -580,7 +674,11 @@ inline unsigned int Accessor::GetElementSize() { return GetNumComponents() * GetBytesPerComponent(); } +// wangyi 0506 inline uint8_t *Accessor::GetPointer() { + if (sparse) + return sparse->data.data(); + if (!bufferView || !bufferView->buffer) return 0; uint8_t *basePtr = bufferView->buffer->GetPointer(); if (!basePtr) return 0; @@ -635,7 +733,8 @@ void Accessor::ExtractData(T *&outData) const size_t targetElemSize = sizeof(T); ai_assert(elemSize <= targetElemSize); - ai_assert(count * stride <= bufferView->byteLength); + //wangyi 0506 + ai_assert(count * stride <= (bufferView ? bufferView->byteLength : sparse->data.size())); outData = new T[count]; if (stride == elemSize && targetElemSize == elemSize) { @@ -660,6 +759,35 @@ inline void Accessor::WriteData(size_t _count, const void *src_buffer, size_t sr CopyData(_count, src, src_stride, dst, dst_stride); } +//wangyi 0506 +inline void Accessor::WriteSparseValues(size_t _count, const void *src_data, size_t src_dataStride) { + if (!sparse) + return; + + // values + uint8_t *value_buffer_ptr = sparse->values->buffer->GetPointer(); + size_t value_offset = sparse->valuesByteOffset + sparse->values->byteOffset; + size_t value_dst_stride = GetNumComponents() * GetBytesPerComponent(); + const uint8_t *value_src = reinterpret_cast(src_data); + uint8_t *value_dst = reinterpret_cast(value_buffer_ptr + value_offset); + ai_assert(value_dst + _count * value_dst_stride <= value_buffer_ptr + sparse->values->buffer->byteLength); + CopyData(_count, value_src, src_dataStride, value_dst, value_dst_stride); +} + +//wangyi 0506 +inline void Accessor::WriteSparseIndices(size_t _count, const void *src_idx, size_t src_idxStride) { + if (!sparse) + return; + + // indices + uint8_t *indices_buffer_ptr = sparse->indices->buffer->GetPointer(); + size_t indices_offset = sparse->indicesByteOffset + sparse->indices->byteOffset; + size_t indices_dst_stride = 1 * sizeof(unsigned short); + const uint8_t *indices_src = reinterpret_cast(src_idx); + uint8_t *indices_dst = reinterpret_cast(indices_buffer_ptr + indices_offset); + ai_assert(indices_dst + _count * indices_dst_stride <= indices_buffer_ptr + sparse->indices->buffer->byteLength); + CopyData(_count, indices_src, src_idxStride, indices_dst, indices_dst_stride); +} inline Accessor::Indexer::Indexer(Accessor &acc) : accessor(acc), data(acc.GetPointer()), elemSize(acc.GetElementSize()), stride(acc.bufferView && acc.bufferView->byteStride ? acc.bufferView->byteStride : elemSize) { } diff --git a/code/AssetLib/glTF2/glTF2AssetWriter.inl b/code/AssetLib/glTF2/glTF2AssetWriter.inl index 798f38c1c..5e936384f 100644 --- a/code/AssetLib/glTF2/glTF2AssetWriter.inl +++ b/code/AssetLib/glTF2/glTF2AssetWriter.inl @@ -107,21 +107,49 @@ namespace glTF2 { inline void Write(Value& obj, Accessor& a, AssetWriter& w) { - obj.AddMember("bufferView", a.bufferView->index, w.mAl); - obj.AddMember("byteOffset", (unsigned int)a.byteOffset, w.mAl); + //wangyi 0506 + if (a.bufferView) { + obj.AddMember("bufferView", a.bufferView->index, w.mAl); + obj.AddMember("byteOffset", (unsigned int)a.byteOffset, w.mAl); + Value vTmpMax, vTmpMin; + if (a.componentType == ComponentType_FLOAT) { + obj.AddMember("max", MakeValue(vTmpMax, a.max, w.mAl), w.mAl); + obj.AddMember("min", MakeValue(vTmpMin, a.min, w.mAl), w.mAl); + } else { + obj.AddMember("max", MakeValueCast(vTmpMax, a.max, w.mAl), w.mAl); + obj.AddMember("min", MakeValueCast(vTmpMin, a.min, w.mAl), w.mAl); + } + } obj.AddMember("componentType", int(a.componentType), w.mAl); obj.AddMember("count", (unsigned int)a.count, w.mAl); obj.AddMember("type", StringRef(AttribType::ToString(a.type)), w.mAl); - Value vTmpMax, vTmpMin; - if (a.componentType == ComponentType_FLOAT) { - obj.AddMember("max", MakeValue(vTmpMax, a.max, w.mAl), w.mAl); - obj.AddMember("min", MakeValue(vTmpMin, a.min, w.mAl), w.mAl); - } else { - obj.AddMember("max", MakeValueCast(vTmpMax, a.max, w.mAl), w.mAl); - obj.AddMember("min", MakeValueCast(vTmpMin, a.min, w.mAl), w.mAl); - } + // wangyi 0506 + if (a.sparse) { + Value sparseValue; + sparseValue.SetObject(); + + //count + sparseValue.AddMember("count", (unsigned int)a.sparse->count, w.mAl); + + //indices + Value indices; + indices.SetObject(); + indices.AddMember("bufferView", a.sparse->indices->index, w.mAl); + indices.AddMember("byteOffset", (unsigned int)a.sparse->indicesByteOffset, w.mAl); + indices.AddMember("componentType", int(a.sparse->indicesType), w.mAl); + sparseValue.AddMember("indices", indices, w.mAl); + + //values + Value values; + values.SetObject(); + values.AddMember("bufferView", a.sparse->values->index, w.mAl); + values.AddMember("byteOffset", (unsigned int)a.sparse->valuesByteOffset, w.mAl); + sparseValue.AddMember("values", values, w.mAl); + + obj.AddMember("sparse", sparseValue, w.mAl); + } } inline void Write(Value& obj, Animation& a, AssetWriter& w) diff --git a/code/AssetLib/glTF2/glTF2Exporter.cpp b/code/AssetLib/glTF2/glTF2Exporter.cpp index da6d9ab2e..8d6471db2 100644 --- a/code/AssetLib/glTF2/glTF2Exporter.cpp +++ b/code/AssetLib/glTF2/glTF2Exporter.cpp @@ -207,6 +207,152 @@ inline void SetAccessorRange(ComponentType compType, Ref acc, void* da } } +// wangyi 0506 +// compute the (data-dataBase), store the non-zero data items +template +size_t NZDiff(void *data, void *dataBase, size_t count, unsigned int numCompsIn, unsigned int numCompsOut, void *&outputNZDiff, void *&outputNZIdx) { + std::vector vNZDiff; + std::vector vNZIdx; + size_t totalComps = count * numCompsIn; + T *bufferData_ptr = static_cast(data); + T *bufferData_end = bufferData_ptr + totalComps; + T *bufferBase_ptr = static_cast(dataBase); + + // Search and set extreme values. + for (short idx = 0; bufferData_ptr < bufferData_end; idx += 1, bufferData_ptr += numCompsIn) { + bool bNonZero = false; + + //for the data, check any component Non Zero + for (unsigned int j = 0; j < numCompsOut; j++) { + double valueData = bufferData_ptr[j]; + double valueBase = bufferBase_ptr ? bufferBase_ptr[j] : 0; + if ((valueData - valueBase) != 0) { + bNonZero = true; + break; + } + } + + //all zeros, continue + if (!bNonZero) + continue; + + //non zero, store the data + for (unsigned int j = 0; j < numCompsOut; j++) { + T valueData = bufferData_ptr[j]; + T valueBase = bufferBase_ptr ? bufferBase_ptr[j] : 0; + vNZDiff.push_back(valueData - valueBase); + } + vNZIdx.push_back(idx); + } + + //process data + outputNZDiff = new T[vNZDiff.size()]; + memcpy(outputNZDiff, vNZDiff.data(), vNZDiff.size() * sizeof(T)); + + outputNZIdx = new unsigned short[vNZIdx.size()]; + memcpy(outputNZIdx, vNZIdx.data(), vNZIdx.size() * sizeof(unsigned short)); + return vNZIdx.size(); +} + +inline size_t NZDiff(ComponentType compType, void *data, void *dataBase, size_t count, unsigned int numCompsIn, unsigned int numCompsOut, void *&nzDiff, void *&nzIdx) { + switch (compType) { + case ComponentType_SHORT: + return NZDiff(data, dataBase, count, numCompsIn, numCompsOut, nzDiff, nzIdx); + case ComponentType_UNSIGNED_SHORT: + return NZDiff(data, dataBase, count, numCompsIn, numCompsOut, nzDiff, nzIdx); + case ComponentType_UNSIGNED_INT: + return NZDiff(data, dataBase, count, numCompsIn, numCompsOut, nzDiff, nzIdx); + case ComponentType_FLOAT: + return NZDiff(data, dataBase, count, numCompsIn, numCompsOut, nzDiff, nzIdx); + case ComponentType_BYTE: + return NZDiff(data, dataBase, count, numCompsIn, numCompsOut, nzDiff, nzIdx); + case ComponentType_UNSIGNED_BYTE: + return NZDiff(data, dataBase, count, numCompsIn, numCompsOut, nzDiff, nzIdx); + } + return 0; +} +// wangyi 0506 +inline Ref ExportDataSparse(Asset &a, std::string &meshName, Ref &buffer, + size_t count, void *data, AttribType::Value typeIn, AttribType::Value typeOut, ComponentType compType, BufferViewTarget target = BufferViewTarget_NONE, void *dataBase = 0) { + if (!count || !data) { + return Ref(); + } + + unsigned int numCompsIn = AttribType::GetNumComponents(typeIn); + unsigned int numCompsOut = AttribType::GetNumComponents(typeOut); + unsigned int bytesPerComp = ComponentTypeSize(compType); + + // accessor + Ref acc = a.accessors.Create(a.FindUniqueID(meshName, "accessor")); + + // if there is a basic data vector + if (dataBase) { + size_t base_offset = buffer->byteLength; + size_t base_padding = base_offset % bytesPerComp; + base_offset += base_padding; + size_t base_length = count * numCompsOut * bytesPerComp; + buffer->Grow(base_length + base_padding); + + Ref bv = a.bufferViews.Create(a.FindUniqueID(meshName, "view")); + bv->buffer = buffer; + bv->byteOffset = base_offset; + bv->byteLength = base_length; //! The target that the WebGL buffer should be bound to. + bv->byteStride = 0; + bv->target = target; + acc->bufferView = bv; + acc->WriteData(count, dataBase, numCompsIn * bytesPerComp); + } + acc->byteOffset = 0; + acc->componentType = compType; + acc->count = count; + acc->type = typeOut; + + if (data) { + void *nzDiff = 0, *nzIdx = 0; + size_t nzCount = NZDiff(compType, data, dataBase, count, numCompsIn, numCompsOut, nzDiff, nzIdx); + acc->sparse.reset(new Accessor::Sparse); + acc->sparse->count = nzCount; + + //indices + unsigned int bytesPerIdx = sizeof(unsigned short); + size_t indices_offset = buffer->byteLength; + size_t indices_padding = indices_offset % bytesPerIdx; + indices_offset += indices_padding; + size_t indices_length = nzCount * 1 * bytesPerIdx; + buffer->Grow(indices_length + indices_padding); + + Ref indicesBV = a.bufferViews.Create(a.FindUniqueID(meshName, "view")); + indicesBV->buffer = buffer; + indicesBV->byteOffset = indices_offset; + indicesBV->byteLength = indices_length; + indicesBV->byteStride = 0; + acc->sparse->indices = indicesBV; + acc->sparse->indicesType = ComponentType_UNSIGNED_SHORT; + acc->sparse->indicesByteOffset = 0; + acc->WriteSparseIndices(nzCount, nzIdx, 1 * bytesPerIdx); + + //values + size_t values_offset = buffer->byteLength; + size_t values_padding = values_offset % bytesPerComp; + values_offset += values_padding; + size_t values_length = nzCount * numCompsOut * bytesPerComp; + buffer->Grow(values_length + values_padding); + + Ref valuesBV = a.bufferViews.Create(a.FindUniqueID(meshName, "view")); + valuesBV->buffer = buffer; + valuesBV->byteOffset = values_offset; + valuesBV->byteLength = values_length; + valuesBV->byteStride = 0; + acc->sparse->values = valuesBV; + acc->sparse->valuesByteOffset = 0; + acc->WriteSparseValues(nzCount, nzDiff, numCompsIn * bytesPerComp); + + //clear + delete[] nzDiff; + delete[] nzIdx; + } + return acc; +} inline Ref ExportData(Asset& a, std::string& meshName, Ref& buffer, size_t count, void* data, AttribType::Value typeIn, AttribType::Value typeOut, ComponentType compType, BufferViewTarget target = BufferViewTarget_NONE) { @@ -828,7 +974,11 @@ void glTF2Exporter::ExportMeshes() for (unsigned int vt = 0; vt < pAnimMesh->mNumVertices; ++vt) { pPositionDiff[vt] = pAnimMesh->mVertices[vt] - aim->mVertices[vt]; } - Ref vec = ExportData(*mAsset, meshId, b, + /*Ref vec = ExportData(*mAsset, meshId, b, + pAnimMesh->mNumVertices, pPositionDiff, + AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT);*/ + //wangyi 0506 + Ref vec = ExportDataSparse(*mAsset, meshId, b, pAnimMesh->mNumVertices, pPositionDiff, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT); if (vec) { @@ -843,6 +993,10 @@ void glTF2Exporter::ExportMeshes() for (unsigned int vt = 0; vt < pAnimMesh->mNumVertices; ++vt) { pNormalDiff[vt] = pAnimMesh->mNormals[vt] - aim->mNormals[vt]; } + /*Ref vec = ExportData(*mAsset, meshId, b, + pAnimMesh->mNumVertices, pNormalDiff, + AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT);*/ + //wangyi 0506 Ref vec = ExportData(*mAsset, meshId, b, pAnimMesh->mNumVertices, pNormalDiff, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT); From b8e39b58d1a5101b88032de00029c3b40d8bf750 Mon Sep 17 00:00:00 2001 From: Yingying Wang Date: Fri, 15 May 2020 12:32:58 -0700 Subject: [PATCH 02/62] clean up --- code/AssetLib/glTF2/glTF2Asset.h | 7 ++----- code/AssetLib/glTF2/glTF2Asset.inl | 10 +--------- code/AssetLib/glTF2/glTF2AssetWriter.inl | 2 -- code/AssetLib/glTF2/glTF2Exporter.cpp | 21 ++++++++++----------- 4 files changed, 13 insertions(+), 27 deletions(-) diff --git a/code/AssetLib/glTF2/glTF2Asset.h b/code/AssetLib/glTF2/glTF2Asset.h index a60ac98f3..b413f1fe7 100644 --- a/code/AssetLib/glTF2/glTF2Asset.h +++ b/code/AssetLib/glTF2/glTF2Asset.h @@ -367,7 +367,7 @@ struct Object { //! An accessor provides a typed view into a BufferView or a subset of a BufferView //! similar to how WebGL's vertexAttribPointer() defines an attribute in a buffer. struct Accessor : public Object { - struct Sparse; //wangyi 0506 + struct Sparse; Ref bufferView; //!< The ID of the bufferView. (required) size_t byteOffset; //!< The offset relative to the start of the bufferView in bytes. (required) ComponentType componentType; //!< The datatype of components in the attribute. (required) @@ -375,7 +375,7 @@ struct Accessor : public Object { AttribType::Value type; //!< Specifies if the attribute is a scalar, vector, or matrix. (required) std::vector max; //!< Maximum value of each component in this attribute. std::vector min; //!< Minimum value of each component in this attribute. - std::unique_ptr sparse; //wangyi 0506 + std::unique_ptr sparse; unsigned int GetNumComponents(); unsigned int GetBytesPerComponent(); @@ -387,7 +387,6 @@ struct Accessor : public Object { void ExtractData(T *&outData); void WriteData(size_t count, const void *src_buffer, size_t src_stride); - //wangyi 0506 void WriteSparseValues(size_t count, const void *src_data, size_t src_dataStride); void WriteSparseIndices(size_t count, const void *src_idx, size_t src_idxStride); @@ -430,7 +429,6 @@ struct Accessor : public Object { Accessor() {} void Read(Value &obj, Asset &r); - //wangyi 0506 //sparse struct Sparse { size_t count; @@ -577,7 +575,6 @@ struct BufferView : public Object { BufferViewTarget target; //! The target that the WebGL buffer should be bound to. void Read(Value &obj, Asset &r); - //wangyi 0506 uint8_t *GetPointer(size_t accOffset); }; diff --git a/code/AssetLib/glTF2/glTF2Asset.inl b/code/AssetLib/glTF2/glTF2Asset.inl index 09fd48761..b81d73eda 100644 --- a/code/AssetLib/glTF2/glTF2Asset.inl +++ b/code/AssetLib/glTF2/glTF2Asset.inl @@ -550,7 +550,6 @@ inline void BufferView::Read(Value &obj, Asset &r) { byteStride = MemberOrDefault(obj, "byteStride", 0u); } -//wangyi 0506 inline uint8_t *BufferView::GetPointer(size_t accOffset) { if (!buffer) return 0; uint8_t *basePtr = buffer->GetPointer(); @@ -571,7 +570,6 @@ inline uint8_t *BufferView::GetPointer(size_t accOffset) { // struct Accessor // -//wangyi 0506 inline void Accessor::Sparse::PopulateData(size_t numBytes, uint8_t *bytes) { if (bytes) { data.assign(bytes, bytes + numBytes); @@ -610,7 +608,7 @@ inline void Accessor::Sparse::PatchData(unsigned int elementSize) { pIndices += indexSize; } } -// wangyi 0506 + inline void Accessor::Read(Value &obj, Asset &r) { if (Value *bufferViewVal = FindUInt(obj, "bufferView")) { @@ -624,7 +622,6 @@ inline void Accessor::Read(Value &obj, Asset &r) { const char *typestr; type = ReadMember(obj, "type", typestr) ? AttribType::FromString(typestr) : AttribType::SCALAR; - //wangyi 0506 if (Value *sparseValue = FindObject(obj, "sparse")) { sparse.reset(new Sparse); // count @@ -674,7 +671,6 @@ inline unsigned int Accessor::GetElementSize() { return GetNumComponents() * GetBytesPerComponent(); } -// wangyi 0506 inline uint8_t *Accessor::GetPointer() { if (sparse) return sparse->data.data(); @@ -732,8 +728,6 @@ void Accessor::ExtractData(T *&outData) const size_t targetElemSize = sizeof(T); ai_assert(elemSize <= targetElemSize); - - //wangyi 0506 ai_assert(count * stride <= (bufferView ? bufferView->byteLength : sparse->data.size())); outData = new T[count]; @@ -759,7 +753,6 @@ inline void Accessor::WriteData(size_t _count, const void *src_buffer, size_t sr CopyData(_count, src, src_stride, dst, dst_stride); } -//wangyi 0506 inline void Accessor::WriteSparseValues(size_t _count, const void *src_data, size_t src_dataStride) { if (!sparse) return; @@ -774,7 +767,6 @@ inline void Accessor::WriteSparseValues(size_t _count, const void *src_data, siz CopyData(_count, value_src, src_dataStride, value_dst, value_dst_stride); } -//wangyi 0506 inline void Accessor::WriteSparseIndices(size_t _count, const void *src_idx, size_t src_idxStride) { if (!sparse) return; diff --git a/code/AssetLib/glTF2/glTF2AssetWriter.inl b/code/AssetLib/glTF2/glTF2AssetWriter.inl index 5e936384f..6d7e28738 100644 --- a/code/AssetLib/glTF2/glTF2AssetWriter.inl +++ b/code/AssetLib/glTF2/glTF2AssetWriter.inl @@ -107,7 +107,6 @@ namespace glTF2 { inline void Write(Value& obj, Accessor& a, AssetWriter& w) { - //wangyi 0506 if (a.bufferView) { obj.AddMember("bufferView", a.bufferView->index, w.mAl); obj.AddMember("byteOffset", (unsigned int)a.byteOffset, w.mAl); @@ -125,7 +124,6 @@ namespace glTF2 { obj.AddMember("count", (unsigned int)a.count, w.mAl); obj.AddMember("type", StringRef(AttribType::ToString(a.type)), w.mAl); - // wangyi 0506 if (a.sparse) { Value sparseValue; sparseValue.SetObject(); diff --git a/code/AssetLib/glTF2/glTF2Exporter.cpp b/code/AssetLib/glTF2/glTF2Exporter.cpp index 8d6471db2..41fe4c9c8 100644 --- a/code/AssetLib/glTF2/glTF2Exporter.cpp +++ b/code/AssetLib/glTF2/glTF2Exporter.cpp @@ -207,7 +207,6 @@ inline void SetAccessorRange(ComponentType compType, Ref acc, void* da } } -// wangyi 0506 // compute the (data-dataBase), store the non-zero data items template size_t NZDiff(void *data, void *dataBase, size_t count, unsigned int numCompsIn, unsigned int numCompsOut, void *&outputNZDiff, void *&outputNZIdx) { @@ -271,7 +270,7 @@ inline size_t NZDiff(ComponentType compType, void *data, void *dataBase, size_t } return 0; } -// wangyi 0506 + inline Ref ExportDataSparse(Asset &a, std::string &meshName, Ref &buffer, size_t count, void *data, AttribType::Value typeIn, AttribType::Value typeOut, ComponentType compType, BufferViewTarget target = BufferViewTarget_NONE, void *dataBase = 0) { if (!count || !data) { @@ -974,13 +973,13 @@ void glTF2Exporter::ExportMeshes() for (unsigned int vt = 0; vt < pAnimMesh->mNumVertices; ++vt) { pPositionDiff[vt] = pAnimMesh->mVertices[vt] - aim->mVertices[vt]; } - /*Ref vec = ExportData(*mAsset, meshId, b, - pAnimMesh->mNumVertices, pPositionDiff, - AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT);*/ - //wangyi 0506 - Ref vec = ExportDataSparse(*mAsset, meshId, b, + Ref vec = ExportData(*mAsset, meshId, b, pAnimMesh->mNumVertices, pPositionDiff, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT); + /* sparse + Ref vec = ExportDataSparse(*mAsset, meshId, b, + pAnimMesh->mNumVertices, pPositionDiff, + AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT);*/ if (vec) { p.targets[am].position.push_back(vec); } @@ -993,13 +992,13 @@ void glTF2Exporter::ExportMeshes() for (unsigned int vt = 0; vt < pAnimMesh->mNumVertices; ++vt) { pNormalDiff[vt] = pAnimMesh->mNormals[vt] - aim->mNormals[vt]; } - /*Ref vec = ExportData(*mAsset, meshId, b, - pAnimMesh->mNumVertices, pNormalDiff, - AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT);*/ - //wangyi 0506 Ref vec = ExportData(*mAsset, meshId, b, pAnimMesh->mNumVertices, pNormalDiff, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT); + /* sparse + Ref vec = ExportDataSparse(*mAsset, meshId, b, + pAnimMesh->mNumVertices, pNormalDiff, + AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT);*/ if (vec) { p.targets[am].normal.push_back(vec); } From 50f0a86798399d474495da22d045d4da543ed481 Mon Sep 17 00:00:00 2001 From: Yingying Wang Date: Tue, 19 May 2020 16:10:41 -0700 Subject: [PATCH 03/62] conditional export --- code/AssetLib/glTF2/glTF2Exporter.cpp | 45 +++++++++++++++++---------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/code/AssetLib/glTF2/glTF2Exporter.cpp b/code/AssetLib/glTF2/glTF2Exporter.cpp index 088503636..072809dc4 100644 --- a/code/AssetLib/glTF2/glTF2Exporter.cpp +++ b/code/AssetLib/glTF2/glTF2Exporter.cpp @@ -969,10 +969,15 @@ void glTF2Exporter::ExportMeshes() /*************** Targets for blendshapes ****************/ if (aim->mNumAnimMeshes > 0) { + //wangyi 0506 + bool bUseSparse = this->mProperties->HasPropertyBool("GLTF2_SPARSE_ACCESSOR_EXP") && + this->mProperties->GetPropertyBool("GLTF2_SPARSE_ACCESSOR_EXP"); + bool bIncludeNormal = this->mProperties->HasPropertyBool("GLTF2_TARGET_NORMAL_EXP") && + this->mProperties->GetPropertyBool("GLTF2_TARGET_NORMAL_EXP"); + p.targets.resize(aim->mNumAnimMeshes); for (unsigned int am = 0; am < aim->mNumAnimMeshes; ++am) { aiAnimMesh *pAnimMesh = aim->mAnimMeshes[am]; - // position if (pAnimMesh->HasPositions()) { // NOTE: in gltf it is the diff stored @@ -980,13 +985,17 @@ void glTF2Exporter::ExportMeshes() for (unsigned int vt = 0; vt < pAnimMesh->mNumVertices; ++vt) { pPositionDiff[vt] = pAnimMesh->mVertices[vt] - aim->mVertices[vt]; } - Ref vec = ExportData(*mAsset, meshId, b, - pAnimMesh->mNumVertices, pPositionDiff, - AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT); - /* sparse - Ref vec = ExportDataSparse(*mAsset, meshId, b, - pAnimMesh->mNumVertices, pPositionDiff, - AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT);*/ + //wangyi 0506 + Ref vec; + if (bUseSparse) { + vec = ExportDataSparse(*mAsset, meshId, b, + pAnimMesh->mNumVertices, pPositionDiff, + AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT); + } else { + vec = ExportData(*mAsset, meshId, b, + pAnimMesh->mNumVertices, pPositionDiff, + AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT); + } if (vec) { p.targets[am].position.push_back(vec); } @@ -994,18 +1003,22 @@ void glTF2Exporter::ExportMeshes() } // normal - if (pAnimMesh->HasNormals()) { + if (pAnimMesh->HasNormals() && bIncludeNormal) { aiVector3D *pNormalDiff = new aiVector3D[pAnimMesh->mNumVertices]; for (unsigned int vt = 0; vt < pAnimMesh->mNumVertices; ++vt) { pNormalDiff[vt] = pAnimMesh->mNormals[vt] - aim->mNormals[vt]; } - Ref vec = ExportData(*mAsset, meshId, b, - pAnimMesh->mNumVertices, pNormalDiff, - AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT); - /* sparse - Ref vec = ExportDataSparse(*mAsset, meshId, b, - pAnimMesh->mNumVertices, pNormalDiff, - AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT);*/ + //wangyi 0506 + Ref vec; + if (bUseSparse) { + vec = ExportDataSparse(*mAsset, meshId, b, + pAnimMesh->mNumVertices, pNormalDiff, + AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT); + } else { + vec = ExportData(*mAsset, meshId, b, + pAnimMesh->mNumVertices, pNormalDiff, + AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT); + } if (vec) { p.targets[am].normal.push_back(vec); } From 87584eb007df4dda029cbac5e328941742129d5d Mon Sep 17 00:00:00 2001 From: FRICOTEAUX Date: Thu, 28 May 2020 11:05:38 +0200 Subject: [PATCH 04/62] glTF2: fix "file size doesn't match" issue when importing GLB in Blender --- code/glTF2/glTF2AssetWriter.inl | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/code/glTF2/glTF2AssetWriter.inl b/code/glTF2/glTF2AssetWriter.inl index 02c14980d..f9bbb7ef7 100644 --- a/code/glTF2/glTF2AssetWriter.inl +++ b/code/glTF2/glTF2AssetWriter.inl @@ -672,10 +672,13 @@ namespace glTF2 { // Binary chunk // + int GLB_Chunk_count = 1; uint32_t binaryChunkLength = 0; if (bodyBuffer->byteLength > 0) { binaryChunkLength = (bodyBuffer->byteLength + 3) & ~3; // Round up to next multiple of 4 - auto paddingLength = binaryChunkLength - bodyBuffer->byteLength; + + auto curPaddingLength = binaryChunkLength - bodyBuffer->byteLength; + ++GLB_Chunk_count; GLB_Chunk binaryChunk; binaryChunk.chunkLength = binaryChunkLength; @@ -690,7 +693,7 @@ namespace glTF2 { if (outfile->Write(bodyBuffer->GetPointer(), 1, bodyBuffer->byteLength) != bodyBuffer->byteLength) { throw DeadlyExportError("Failed to write body data!"); } - if (paddingLength && outfile->Write(&padding, 1, paddingLength) != paddingLength) { + if (curPaddingLength && outfile->Write(&padding, 1, paddingLength) != paddingLength) { throw DeadlyExportError("Failed to write body data padding!"); } } @@ -705,7 +708,7 @@ namespace glTF2 { header.version = 2; AI_SWAP4(header.version); - header.length = uint32_t(sizeof(GLB_Header) + 2 * sizeof(GLB_Chunk) + jsonChunkLength + binaryChunkLength); + header.length = uint32_t(sizeof(GLB_Header) + GLB_Chunk_count * sizeof(GLB_Chunk) + jsonChunkLength + binaryChunkLength); AI_SWAP4(header.length); outfile->Seek(0, aiOrigin_SET); From d40a3026dbacb24e1a1eab65ce0ea2b31dc8b2fd Mon Sep 17 00:00:00 2001 From: kimkulling Date: Thu, 28 May 2020 21:02:13 +0200 Subject: [PATCH 05/62] closes https://github.com/assimp/assimp/issues/3165: fix gcc build. --- code/AssetLib/STL/STLLoader.cpp | 14 ++++++++++++-- code/AssetLib/glTF/glTFAsset.h | 5 +++-- code/AssetLib/glTF2/glTF2Asset.h | 4 +++- code/Common/SceneCombiner.cpp | 5 ++++- code/Common/SpatialSort.cpp | 12 ++++-------- test/unit/utFindInvalidData.cpp | 8 ++++++-- 6 files changed, 32 insertions(+), 16 deletions(-) diff --git a/code/AssetLib/STL/STLLoader.cpp b/code/AssetLib/STL/STLLoader.cpp index 702f4fe5d..7d7fdb7c9 100644 --- a/code/AssetLib/STL/STLLoader.cpp +++ b/code/AssetLib/STL/STLLoader.cpp @@ -370,13 +370,23 @@ void STLImporter::LoadASCIIFile(aiNode *root) { pMesh->mNumFaces = static_cast(positionBuffer.size() / 3); pMesh->mNumVertices = static_cast(positionBuffer.size()); pMesh->mVertices = new aiVector3D[pMesh->mNumVertices]; - memcpy(pMesh->mVertices, &positionBuffer[0].x, pMesh->mNumVertices * sizeof(aiVector3D)); + for (size_t i=0; imNumVertices; ++i ) { + pMesh->mVertices[i].x = positionBuffer[i].x; + pMesh->mVertices[i].y = positionBuffer[i].y; + pMesh->mVertices[i].z = positionBuffer[i].z; + } + //memcpy(pMesh->mVertices, &positionBuffer[0].x, pMesh->mNumVertices * sizeof(aiVector3D)); positionBuffer.clear(); } // also only process normalBuffer when filled, else exception when accessing with index operator if (!normalBuffer.empty()) { pMesh->mNormals = new aiVector3D[pMesh->mNumVertices]; - memcpy(pMesh->mNormals, &normalBuffer[0].x, pMesh->mNumVertices * sizeof(aiVector3D)); + for (size_t i=0; imNumVertices; ++i ) { + pMesh->mNormals[i].x = normalBuffer[i].x; + pMesh->mNormals[i].y = normalBuffer[i].y; + pMesh->mNormals[i].z = normalBuffer[i].z; + } +// memcpy(pMesh->mNormals, &normalBuffer[0].x, pMesh->mNumVertices * sizeof(aiVector3D)); normalBuffer.clear(); } diff --git a/code/AssetLib/glTF/glTFAsset.h b/code/AssetLib/glTF/glTFAsset.h index 4c7aaa908..56cf18527 100644 --- a/code/AssetLib/glTF/glTFAsset.h +++ b/code/AssetLib/glTF/glTFAsset.h @@ -4,7 +4,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2020, assimp team - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -62,10 +61,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #define RAPIDJSON_HAS_STDSTRING 1 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wclass-memaccess" #include #include #include - +#pragma GCC diagnostic pop #ifdef ASSIMP_API # include # include diff --git a/code/AssetLib/glTF2/glTF2Asset.h b/code/AssetLib/glTF2/glTF2Asset.h index bfd4e4342..ed5f4318a 100644 --- a/code/AssetLib/glTF2/glTF2Asset.h +++ b/code/AssetLib/glTF2/glTF2Asset.h @@ -64,10 +64,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #define RAPIDJSON_HAS_STDSTRING 1 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wclass-memaccess" #include #include #include - +#pragma GCC diagnostic pop #ifdef ASSIMP_API #include #include diff --git a/code/Common/SceneCombiner.cpp b/code/Common/SceneCombiner.cpp index 4d2a411f2..2aa855989 100644 --- a/code/Common/SceneCombiner.cpp +++ b/code/Common/SceneCombiner.cpp @@ -978,7 +978,10 @@ void GetArrayCopy(Type*& dest, ai_uint num ) { Type* old = dest; dest = new Type[num]; - ::memcpy(dest, old, sizeof(Type) * num); + for ( size_t i=0; imNormals, 0, mMesh->mNumVertices * sizeof(aiVector3D)); - ::memset(mMesh->mBitangents, 0, mMesh->mNumVertices * sizeof(aiVector3D)); + for ( size_t i=0; imNumVertices; ++i ) { + mMesh->mNormals[i].x = mMesh->mNormals[i].y = mMesh->mNormals[i].z =0; + mMesh->mBitangents[i].x = mMesh->mBitangents[i].y = mMesh->mBitangents[i].z = 0; + } + //::memset(mMesh->mNormals, 0, mMesh->mNumVertices * sizeof(aiVector3D)); + //::memset(mMesh->mBitangents, 0, mMesh->mNumVertices * sizeof(aiVector3D)); mMesh->mTextureCoords[2][455] = aiVector3D(std::numeric_limits::quiet_NaN()); From d4ca91f408a3e8e10de029cfb8bc9bad7a72d155 Mon Sep 17 00:00:00 2001 From: Hanif Bin Ariffin Date: Thu, 28 May 2020 19:20:54 -0400 Subject: [PATCH 06/62] Evaluated the following expressions to either values. --- contrib/Open3DGC/o3dgcSC3DMCDecoder.inl | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/contrib/Open3DGC/o3dgcSC3DMCDecoder.inl b/contrib/Open3DGC/o3dgcSC3DMCDecoder.inl index 326297426..c965fcd50 100644 --- a/contrib/Open3DGC/o3dgcSC3DMCDecoder.inl +++ b/contrib/Open3DGC/o3dgcSC3DMCDecoder.inl @@ -72,9 +72,12 @@ namespace o3dgc unsigned char mask = bstream.ReadUChar(m_iterator, m_streamType); ifs.SetCCW ((mask & 1) == 1); - ifs.SetSolid ((mask & 2) == 1); - ifs.SetConvex ((mask & 4) == 1); - ifs.SetIsTriangularMesh((mask & 8) == 1); + // (mask & 2) == 1 + ifs.SetSolid (false); + // (mask & 4) == 1 + ifs.SetConvex (false); + // (mask & 8) == 1 + ifs.SetIsTriangularMesh(false); //bool markerBit0 = (mask & 16 ) == 1; //bool markerBit1 = (mask & 32 ) == 1; //bool markerBit2 = (mask & 64 ) == 1; From eceb8aeed1b8fdef84cf98ddc2618dc24bdf0604 Mon Sep 17 00:00:00 2001 From: Hanif Bin Ariffin Date: Thu, 28 May 2020 19:22:06 -0400 Subject: [PATCH 07/62] Cleaned up implicit conversion and code. --- test/unit/utMatrix3x3.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/test/unit/utMatrix3x3.cpp b/test/unit/utMatrix3x3.cpp index 50fa66c50..12a84e0fa 100644 --- a/test/unit/utMatrix3x3.cpp +++ b/test/unit/utMatrix3x3.cpp @@ -73,9 +73,21 @@ TEST_F(utMatrix3x3Test, FromToMatrixTest) { aiVector3D from, to; + auto random_ratio = []() -> float { + return static_cast(rand() / RAND_MAX); + }; + for (int i = 0; i < NUM_SAMPLES; ++i) { - from = aiVector3D(1.f * rand() / RAND_MAX, 1.f * rand() / RAND_MAX, 1.f * rand() / RAND_MAX).Normalize(); - to = aiVector3D(1.f * rand() / RAND_MAX, 1.f * rand() / RAND_MAX, 1.f * rand() / RAND_MAX).Normalize(); + from = aiVector3D( + 1.f * random_ratio(), + 1.f * random_ratio(), + 1.f * random_ratio()) + .Normalize(); + to = aiVector3D( + 1.f * random_ratio(), + 1.f * random_ratio(), + 1.f * random_ratio()) + .Normalize(); aiMatrix3x3::FromToMatrix(from, to, trafo); res = trafo * from; From 7db6475592ef1c0d34227c2a7c682c3d4a63cac2 Mon Sep 17 00:00:00 2001 From: Hanif Bin Ariffin Date: Fri, 29 May 2020 11:59:28 -0400 Subject: [PATCH 08/62] Change from (int division -> cast) to (cast -> float division) --- test/unit/utMatrix3x3.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/utMatrix3x3.cpp b/test/unit/utMatrix3x3.cpp index 12a84e0fa..3905b1d35 100644 --- a/test/unit/utMatrix3x3.cpp +++ b/test/unit/utMatrix3x3.cpp @@ -74,7 +74,7 @@ TEST_F(utMatrix3x3Test, FromToMatrixTest) { aiVector3D from, to; auto random_ratio = []() -> float { - return static_cast(rand() / RAND_MAX); + return static_cast(rand()) / static_cast(RAND_MAX); }; for (int i = 0; i < NUM_SAMPLES; ++i) { From 4e34853ac717f2718eade04888b0cb8b9ada5f1e Mon Sep 17 00:00:00 2001 From: Yingying Wang Date: Fri, 5 Jun 2020 12:17:27 -0700 Subject: [PATCH 09/62] gltf2 export target names for blendshapes --- code/AssetLib/glTF2/glTF2AssetWriter.inl | 16 ++++++++++++++++ code/AssetLib/glTF2/glTF2Exporter.cpp | 5 +++++ 2 files changed, 21 insertions(+) diff --git a/code/AssetLib/glTF2/glTF2AssetWriter.inl b/code/AssetLib/glTF2/glTF2AssetWriter.inl index 361af40cd..d5b478e35 100644 --- a/code/AssetLib/glTF2/glTF2AssetWriter.inl +++ b/code/AssetLib/glTF2/glTF2AssetWriter.inl @@ -468,6 +468,22 @@ namespace glTF2 { } obj.AddMember("primitives", primitives, w.mAl); + // targetNames + if (m.targetNames.size() > 0) { + Value extras; + extras.SetObject(); + Value targetNames; + targetNames.SetArray(); + targetNames.Reserve(unsigned(m.targetNames.size()), w.mAl); + for (unsigned int n = 0; n < m.targetNames.size(); ++n) { + std::string name = m.targetNames[n]; + Value tname; + tname.SetString(name.c_str(), w.mAl); + targetNames.PushBack(tname, w.mAl); + } + extras.AddMember("targetNames", targetNames, w.mAl); + obj.AddMember("extras", extras, w.mAl); + } } inline void Write(Value& obj, Node& n, AssetWriter& w) diff --git a/code/AssetLib/glTF2/glTF2Exporter.cpp b/code/AssetLib/glTF2/glTF2Exporter.cpp index 566f95e80..2359851f1 100644 --- a/code/AssetLib/glTF2/glTF2Exporter.cpp +++ b/code/AssetLib/glTF2/glTF2Exporter.cpp @@ -824,9 +824,14 @@ void glTF2Exporter::ExportMeshes() /*************** Targets for blendshapes ****************/ if (aim->mNumAnimMeshes > 0) { + bool bExportTargetNames = this->mProperties->HasPropertyBool("GLTF2_TARGETNAMES_EXP") && + this->mProperties->GetPropertyBool("GLTF2_TARGETNAMES_EXP"); + p.targets.resize(aim->mNumAnimMeshes); for (unsigned int am = 0; am < aim->mNumAnimMeshes; ++am) { aiAnimMesh *pAnimMesh = aim->mAnimMeshes[am]; + if (bExportTargetNames) + m->targetNames.push_back(pAnimMesh->mName.data); // position if (pAnimMesh->HasPositions()) { From 62273b63e5dff9c9b120e1f7345616ff82695811 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 6 Jun 2020 12:22:01 +0200 Subject: [PATCH 10/62] closes https://github.com/assimp/assimp/issues/3256: Remove redundand code --- code/AssetLib/M3D/m3d.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/AssetLib/M3D/m3d.h b/code/AssetLib/M3D/m3d.h index 75bcdfeb7..3d7a2564c 100644 --- a/code/AssetLib/M3D/m3d.h +++ b/code/AssetLib/M3D/m3d.h @@ -5071,7 +5071,7 @@ unsigned char *m3d_save(m3d_t *model, int quality, int flags, unsigned int *size ptr += sprintf(ptr, "\r\n"); } /* mathematical shapes face */ - if (model->numshape && model->numshape && !(flags & M3D_EXP_NOFACE)) { + if (model->numshape !(flags & M3D_EXP_NOFACE)) { for (j = 0; j < model->numshape; j++) { sn = _m3d_safestr(model->shape[j].name, 0); if (!sn) { From 2c0df39ef30621b330f988afc70f1e3ac85b536b Mon Sep 17 00:00:00 2001 From: Alec Date: Sat, 6 Jun 2020 14:33:41 +0200 Subject: [PATCH 11/62] Added rapidjson define to avoid warnings in c++17 --- code/AssetLib/glTF/glTFAsset.h | 1 + code/AssetLib/glTF/glTFCommon.h | 1 + code/AssetLib/glTF2/glTF2Asset.h | 1 + 3 files changed, 3 insertions(+) diff --git a/code/AssetLib/glTF/glTFAsset.h b/code/AssetLib/glTF/glTFAsset.h index 4c7aaa908..f0333ad0c 100644 --- a/code/AssetLib/glTF/glTFAsset.h +++ b/code/AssetLib/glTF/glTFAsset.h @@ -62,6 +62,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #define RAPIDJSON_HAS_STDSTRING 1 +#define RAPIDJSON_NOMEMBERITERATORCLASS #include #include #include diff --git a/code/AssetLib/glTF/glTFCommon.h b/code/AssetLib/glTF/glTFCommon.h index d161e8cd6..b151918b6 100644 --- a/code/AssetLib/glTF/glTFCommon.h +++ b/code/AssetLib/glTF/glTFCommon.h @@ -53,6 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #define RAPIDJSON_HAS_STDSTRING 1 +#define RAPIDJSON_NOMEMBERITERATORCLASS #include #include #include diff --git a/code/AssetLib/glTF2/glTF2Asset.h b/code/AssetLib/glTF2/glTF2Asset.h index 99bcaf072..fc0fe1544 100644 --- a/code/AssetLib/glTF2/glTF2Asset.h +++ b/code/AssetLib/glTF2/glTF2Asset.h @@ -64,6 +64,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #define RAPIDJSON_HAS_STDSTRING 1 +#define RAPIDJSON_NOMEMBERITERATORCLASS #include #include #include From b37d42f6b548a42732abdee2fab84c322021443e Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 7 Jun 2020 18:03:47 +0200 Subject: [PATCH 12/62] Perform sanity check only in debug closes https://github.com/assimp/assimp/issues/3255 --- code/AssetLib/Blender/BlenderDNA.inl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/AssetLib/Blender/BlenderDNA.inl b/code/AssetLib/Blender/BlenderDNA.inl index a41ceab7f..e59adab1d 100644 --- a/code/AssetLib/Blender/BlenderDNA.inl +++ b/code/AssetLib/Blender/BlenderDNA.inl @@ -4,7 +4,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2020, assimp team - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -239,11 +238,13 @@ bool Structure :: ReadFieldPtr(TOUT (&out)[N], const char* name, try { f = &(*this)[name]; +#ifdef _DEBUG // sanity check, should never happen if the genblenddna script is right if ((FieldFlag_Pointer|FieldFlag_Pointer) != (f->flags & (FieldFlag_Pointer|FieldFlag_Pointer))) { throw Error((Formatter::format(),"Field `",name,"` of structure `", this->name,"` ought to be a pointer AND an array")); } +#endif // _DEBUG db.reader->IncPtr(f->offset); From 26421aebc99fadf30334571f70b48f677296c77e Mon Sep 17 00:00:00 2001 From: Yingying Wang Date: Mon, 8 Jun 2020 13:33:16 -0700 Subject: [PATCH 13/62] support channel name in blendshape name --- code/AssetLib/FBX/FBXConverter.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/AssetLib/FBX/FBXConverter.cpp b/code/AssetLib/FBX/FBXConverter.cpp index eb995f429..261567e48 100644 --- a/code/AssetLib/FBX/FBXConverter.cpp +++ b/code/AssetLib/FBX/FBXConverter.cpp @@ -1163,7 +1163,8 @@ unsigned int FBXConverter::ConvertMeshSingleMaterial(const MeshGeometry &mesh, c const std::vector &curVertices = shapeGeometry->GetVertices(); const std::vector &curNormals = shapeGeometry->GetNormals(); const std::vector &curIndices = shapeGeometry->GetIndices(); - animMesh->mName.Set(FixAnimMeshName(shapeGeometry->Name())); + //losing channel name if using shapeGeometry->Name() + animMesh->mName.Set(FixAnimMeshName(blendShapeChannel->Name())); for (size_t j = 0; j < curIndices.size(); j++) { const unsigned int curIndex = curIndices.at(j); aiVector3D vertex = curVertices.at(j); From 206551247050a02cf21bdf1b5cf45190af38492a Mon Sep 17 00:00:00 2001 From: Yingying Wang Date: Mon, 8 Jun 2020 14:41:53 -0700 Subject: [PATCH 14/62] remove comments --- code/AssetLib/glTF2/glTF2Exporter.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/code/AssetLib/glTF2/glTF2Exporter.cpp b/code/AssetLib/glTF2/glTF2Exporter.cpp index 072809dc4..def4268a1 100644 --- a/code/AssetLib/glTF2/glTF2Exporter.cpp +++ b/code/AssetLib/glTF2/glTF2Exporter.cpp @@ -969,7 +969,6 @@ void glTF2Exporter::ExportMeshes() /*************** Targets for blendshapes ****************/ if (aim->mNumAnimMeshes > 0) { - //wangyi 0506 bool bUseSparse = this->mProperties->HasPropertyBool("GLTF2_SPARSE_ACCESSOR_EXP") && this->mProperties->GetPropertyBool("GLTF2_SPARSE_ACCESSOR_EXP"); bool bIncludeNormal = this->mProperties->HasPropertyBool("GLTF2_TARGET_NORMAL_EXP") && @@ -985,7 +984,6 @@ void glTF2Exporter::ExportMeshes() for (unsigned int vt = 0; vt < pAnimMesh->mNumVertices; ++vt) { pPositionDiff[vt] = pAnimMesh->mVertices[vt] - aim->mVertices[vt]; } - //wangyi 0506 Ref vec; if (bUseSparse) { vec = ExportDataSparse(*mAsset, meshId, b, @@ -1008,7 +1006,6 @@ void glTF2Exporter::ExportMeshes() for (unsigned int vt = 0; vt < pAnimMesh->mNumVertices; ++vt) { pNormalDiff[vt] = pAnimMesh->mNormals[vt] - aim->mNormals[vt]; } - //wangyi 0506 Ref vec; if (bUseSparse) { vec = ExportDataSparse(*mAsset, meshId, b, From f18f1a35f6026ff14e1f60dc549bad8c69b5e4f0 Mon Sep 17 00:00:00 2001 From: Yingying Wang Date: Mon, 8 Jun 2020 14:49:50 -0700 Subject: [PATCH 15/62] accommodate linux build --- code/AssetLib/glTF2/glTF2Exporter.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/AssetLib/glTF2/glTF2Exporter.cpp b/code/AssetLib/glTF2/glTF2Exporter.cpp index def4268a1..eb642ca08 100644 --- a/code/AssetLib/glTF2/glTF2Exporter.cpp +++ b/code/AssetLib/glTF2/glTF2Exporter.cpp @@ -354,8 +354,8 @@ inline Ref ExportDataSparse(Asset &a, std::string &meshName, RefWriteSparseValues(nzCount, nzDiff, numCompsIn * bytesPerComp); //clear - delete[] nzDiff; - delete[] nzIdx; + delete[] (char*)nzDiff; + delete[] (char*)nzIdx; } return acc; } From 8fed101432ae4f24b69db105971089791a98fee7 Mon Sep 17 00:00:00 2001 From: Yingying Wang Date: Mon, 8 Jun 2020 16:18:11 -0700 Subject: [PATCH 16/62] avoid all zero --- code/AssetLib/glTF2/glTF2Exporter.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/code/AssetLib/glTF2/glTF2Exporter.cpp b/code/AssetLib/glTF2/glTF2Exporter.cpp index eb642ca08..31cd1f1c6 100644 --- a/code/AssetLib/glTF2/glTF2Exporter.cpp +++ b/code/AssetLib/glTF2/glTF2Exporter.cpp @@ -251,6 +251,13 @@ size_t NZDiff(void *data, void *dataBase, size_t count, unsigned int numCompsIn, vNZIdx.push_back(idx); } + //avoid all-0, put 1 item + if (vNZDiff.size() == 0) { + for (unsigned int j = 0; j < numCompsOut; j++) + vNZDiff.push_back(0); + vNZIdx.push_back(0); + } + //process data outputNZDiff = new T[vNZDiff.size()]; memcpy(outputNZDiff, vNZDiff.data(), vNZDiff.size() * sizeof(T)); From 9e46f9751fc81d75791aad02f00b6c1bf104261f Mon Sep 17 00:00:00 2001 From: Paul Arden Date: Tue, 9 Jun 2020 15:49:38 +1000 Subject: [PATCH 17/62] Check for invalid texture coordinate accessor. Fixes #3269. --- code/AssetLib/glTF2/glTF2Importer.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/code/AssetLib/glTF2/glTF2Importer.cpp b/code/AssetLib/glTF2/glTF2Importer.cpp index 83f022e8f..a957d9d9b 100644 --- a/code/AssetLib/glTF2/glTF2Importer.cpp +++ b/code/AssetLib/glTF2/glTF2Importer.cpp @@ -416,6 +416,10 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { attr.color[c]->ExtractData(aim->mColors[c]); } for (size_t tc = 0; tc < attr.texcoord.size() && tc < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++tc) { + if (!attr.texcoord[tc]) { + throw DeadlyImportError("GLTF: Texture coordinate accessor not found or non-contiguous texture coordinate sets"); + } + if (attr.texcoord[tc]->count != aim->mNumVertices) { DefaultLogger::get()->warn("Texcoord stream size in mesh \"" + mesh.name + "\" does not match the vertex count"); From efbabf3b0daccb976639a3734fa9018c4b3e13fa Mon Sep 17 00:00:00 2001 From: David Date: Tue, 9 Jun 2020 08:32:59 +0200 Subject: [PATCH 18/62] Implement contextmanager for load --- port/PyAssimp/pyassimp/core.py | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/port/PyAssimp/pyassimp/core.py b/port/PyAssimp/pyassimp/core.py index 85cfe8233..37beac886 100644 --- a/port/PyAssimp/pyassimp/core.py +++ b/port/PyAssimp/pyassimp/core.py @@ -14,10 +14,13 @@ if sys.version_info >= (3,0): xrange = range -try: import numpy -except ImportError: numpy = None +try: + import numpy +except ImportError: + numpy = None import logging import ctypes +from contextlib import contextmanager logger = logging.getLogger("pyassimp") # attach default null handler to logger so it doesn't complain # even if you don't attach another handler to logger @@ -272,6 +275,13 @@ def recur_pythonize(node, scene): for c in node.children: recur_pythonize(c, scene) +def release(scene): + ''' + Release resources of a loaded scene. + ''' + _assimp_lib.release(ctypes.pointer(scene)) + +@contextmanager def load(filename, file_type = None, processing = postprocess.aiProcess_Triangulate): @@ -319,7 +329,10 @@ def load(filename, raise AssimpError('Could not import file!') scene = _init(model.contents) recur_pythonize(scene.rootnode, scene) - return scene + try: + yield scene + finally: + release(scene) def export(scene, filename, @@ -373,9 +386,6 @@ def export_blob(scene, raise AssimpError('Could not export scene to blob!') return exportBlobPtr -def release(scene): - _assimp_lib.release(ctypes.pointer(scene)) - def _finalize_texture(tex, target): setattr(target, "achformathint", tex.achFormatHint) if numpy: From b84dbb68ecf4d6e30c535c715ebaa88646dbe5db Mon Sep 17 00:00:00 2001 From: David Date: Tue, 9 Jun 2020 08:33:09 +0200 Subject: [PATCH 19/62] Update READMEs --- port/PyAssimp/README.md | 25 ++++++++++--------------- port/PyAssimp/README.rst | 23 ++++++++++------------- 2 files changed, 20 insertions(+), 28 deletions(-) diff --git a/port/PyAssimp/README.md b/port/PyAssimp/README.md index d64d72763..c9944f717 100644 --- a/port/PyAssimp/README.md +++ b/port/PyAssimp/README.md @@ -42,17 +42,14 @@ substituted by assertions ...): ```python -from pyassimp import * -scene = load('hello.3ds') +from pyassimp import load +with load('hello.3ds') as scene: -assert len(scene.meshes) -mesh = scene.meshes[0] + assert len(scene.meshes) + mesh = scene.meshes[0] -assert len(mesh.vertices) -print(mesh.vertices[0]) - -# don't forget this one, or you will leak! -release(scene) + assert len(mesh.vertices) + print(mesh.vertices[0]) ``` @@ -61,13 +58,11 @@ scene: ```python -from pyassimp import * -scene = load('hello.3ds') +from pyassimp import load +with load('hello.3ds') as scene: -for c in scene.rootnode.children: - print(str(c)) - -release(scene) + for c in scene.rootnode.children: + print(str(c)) ``` diff --git a/port/PyAssimp/README.rst b/port/PyAssimp/README.rst index f909e2cd0..03b7968f1 100644 --- a/port/PyAssimp/README.rst +++ b/port/PyAssimp/README.rst @@ -49,30 +49,27 @@ substituted by assertions ...): .. code:: python - from pyassimp import * - scene = load('hello.3ds') + from pyassimp import load + with load('hello.3ds') as scene: - assert len(scene.meshes) - mesh = scene.meshes[0] + assert len(scene.meshes) + mesh = scene.meshes[0] - assert len(mesh.vertices) - print(mesh.vertices[0]) + assert len(mesh.vertices) + print(mesh.vertices[0]) - # don't forget this one, or you will leak! - release(scene) Another example to list the 'top nodes' in a scene: .. code:: python - from pyassimp import * - scene = load('hello.3ds') + from pyassimp import load + with load('hello.3ds') as scene: - for c in scene.rootnode.children: - print(str(c)) + for c in scene.rootnode.children: + print(str(c)) - release(scene) INSTALL ------- From 5c7bed01f1133956d63419220f918577e49dbc03 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 9 Jun 2020 10:06:50 +0200 Subject: [PATCH 20/62] remove dead code. --- code/AssetLib/STL/STLLoader.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/code/AssetLib/STL/STLLoader.cpp b/code/AssetLib/STL/STLLoader.cpp index 7d7fdb7c9..00cfe4b4d 100644 --- a/code/AssetLib/STL/STLLoader.cpp +++ b/code/AssetLib/STL/STLLoader.cpp @@ -5,8 +5,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2020, assimp team - - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -101,11 +99,13 @@ static bool IsAsciiSTL(const char *buffer, unsigned int fileSize) { const char *bufferEnd = buffer + fileSize; - if (!SkipSpaces(&buffer)) + if (!SkipSpaces(&buffer)) { return false; + } - if (buffer + 5 >= bufferEnd) + if (buffer + 5 >= bufferEnd) { return false; + } bool isASCII(strncmp(buffer, "solid", 5) == 0); if (isASCII) { @@ -386,7 +386,6 @@ void STLImporter::LoadASCIIFile(aiNode *root) { pMesh->mNormals[i].y = normalBuffer[i].y; pMesh->mNormals[i].z = normalBuffer[i].z; } -// memcpy(pMesh->mNormals, &normalBuffer[0].x, pMesh->mNumVertices * sizeof(aiVector3D)); normalBuffer.clear(); } From 35fb4c93703790d19aa4407016297fe6c0f873eb Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 9 Jun 2020 10:07:25 +0200 Subject: [PATCH 21/62] Remove dead code --- code/AssetLib/STL/STLLoader.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/code/AssetLib/STL/STLLoader.cpp b/code/AssetLib/STL/STLLoader.cpp index 00cfe4b4d..2d710b084 100644 --- a/code/AssetLib/STL/STLLoader.cpp +++ b/code/AssetLib/STL/STLLoader.cpp @@ -375,7 +375,6 @@ void STLImporter::LoadASCIIFile(aiNode *root) { pMesh->mVertices[i].y = positionBuffer[i].y; pMesh->mVertices[i].z = positionBuffer[i].z; } - //memcpy(pMesh->mVertices, &positionBuffer[0].x, pMesh->mNumVertices * sizeof(aiVector3D)); positionBuffer.clear(); } // also only process normalBuffer when filled, else exception when accessing with index operator From 42afc40d168b0dfdd26794de4b076156e61ad081 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 9 Jun 2020 10:13:43 +0200 Subject: [PATCH 22/62] Disable warning only for gcc 8.0 or greater --- code/AssetLib/glTF/glTFAsset.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/code/AssetLib/glTF/glTFAsset.h b/code/AssetLib/glTF/glTFAsset.h index 56cf18527..50d977603 100644 --- a/code/AssetLib/glTF/glTFAsset.h +++ b/code/AssetLib/glTF/glTFAsset.h @@ -60,13 +60,23 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#ifndef RAPIDJSON_HAS_STDSTRING #define RAPIDJSON_HAS_STDSTRING 1 +#endif + +#if (__GNUC__ == 8 && __GNUC_MINOR__ >= 0) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wclass-memaccess" +#endif + #include #include #include + +#if (__GNUC__ == 8 && __GNUC_MINOR__ >= 0) #pragma GCC diagnostic pop +#endif + #ifdef ASSIMP_API # include # include From 620bebb999e16fcf9dfa2c561b12c261e579b204 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 9 Jun 2020 10:14:57 +0200 Subject: [PATCH 23/62] diable warning only for gcc 8.0 or greater --- code/AssetLib/glTF2/glTF2Asset.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/code/AssetLib/glTF2/glTF2Asset.h b/code/AssetLib/glTF2/glTF2Asset.h index 9c1938123..f70421ef2 100644 --- a/code/AssetLib/glTF2/glTF2Asset.h +++ b/code/AssetLib/glTF2/glTF2Asset.h @@ -4,7 +4,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2020, assimp team - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -63,13 +62,23 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#ifndef RAPIDJSON_HAS_STDSTRING #define RAPIDJSON_HAS_STDSTRING 1 +#endif + +#if (__GNUC__ == 8 && __GNUC_MINOR__ >= 0) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wclass-memaccess" +#endif + #include #include #include + +#if (__GNUC__ == 8 && __GNUC_MINOR__ >= 0) #pragma GCC diagnostic pop +#endif + #ifdef ASSIMP_API #include #include From 88c1509d69994a8433da53c337c2beeb0a28d232 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 9 Jun 2020 10:15:35 +0200 Subject: [PATCH 24/62] Remove dead code --- code/Common/SceneCombiner.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/code/Common/SceneCombiner.cpp b/code/Common/SceneCombiner.cpp index 2b3b701d5..4f262192b 100644 --- a/code/Common/SceneCombiner.cpp +++ b/code/Common/SceneCombiner.cpp @@ -981,7 +981,6 @@ void GetArrayCopy(Type*& dest, ai_uint num ) { for ( size_t i=0; i Date: Tue, 9 Jun 2020 10:16:05 +0200 Subject: [PATCH 25/62] Remove dead code. --- test/unit/utFindInvalidData.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/unit/utFindInvalidData.cpp b/test/unit/utFindInvalidData.cpp index a31479af7..17a9c0379 100644 --- a/test/unit/utFindInvalidData.cpp +++ b/test/unit/utFindInvalidData.cpp @@ -110,8 +110,6 @@ TEST_F(utFindInvalidDataProcess, testStepNegativeResult) { mMesh->mNormals[i].x = mMesh->mNormals[i].y = mMesh->mNormals[i].z =0; mMesh->mBitangents[i].x = mMesh->mBitangents[i].y = mMesh->mBitangents[i].z = 0; } - //::memset(mMesh->mNormals, 0, mMesh->mNumVertices * sizeof(aiVector3D)); - //::memset(mMesh->mBitangents, 0, mMesh->mNumVertices * sizeof(aiVector3D)); mMesh->mTextureCoords[2][455] = aiVector3D(std::numeric_limits::quiet_NaN()); From 578a7ac5022f26facaef146390cedbd5229c347f Mon Sep 17 00:00:00 2001 From: Yingying Wang Date: Tue, 9 Jun 2020 11:20:48 -0700 Subject: [PATCH 26/62] add Callback API in ExporterProperties --- code/Common/Exporter.cpp | 16 ++++- include/assimp/Exporter.hpp | 135 +++++++++++++++++++----------------- 2 files changed, 87 insertions(+), 64 deletions(-) diff --git a/code/Common/Exporter.cpp b/code/Common/Exporter.cpp index c34457be5..e8ee188e6 100644 --- a/code/Common/Exporter.cpp +++ b/code/Common/Exporter.cpp @@ -580,10 +580,24 @@ ExportProperties::ExportProperties(const ExportProperties &other) : mIntProperties(other.mIntProperties) , mFloatProperties(other.mFloatProperties) , mStringProperties(other.mStringProperties) -, mMatrixProperties(other.mMatrixProperties) { +, mMatrixProperties(other.mMatrixProperties) +//wangyi 0608 +, mCallbackProperties(other.mCallbackProperties){ // empty } +//wangyi 0608 +bool ExportProperties::SetPropertyCallback(const char *szName, std::function &f) { + return SetGenericProperty>(mCallbackProperties, szName, f); +} +std::function ExportProperties::GetPropertyCallback(const char *szName) const { + return GetGenericProperty>(mCallbackProperties, szName, 0); +} +//wangyi 0608 +bool ExportProperties::HasPropertyCallback(const char *szName) const { + return HasGenericProperty>(mCallbackProperties, szName); +} + // ------------------------------------------------------------------------------------------------ // Set a configuration property bool ExportProperties::SetPropertyInteger(const char* szName, int iValue) { diff --git a/include/assimp/Exporter.hpp b/include/assimp/Exporter.hpp index dc6661c11..4abea6ad0 100644 --- a/include/assimp/Exporter.hpp +++ b/include/assimp/Exporter.hpp @@ -47,16 +47,18 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define AI_EXPORT_HPP_INC #ifdef __GNUC__ -# pragma GCC system_header +#pragma GCC system_header #endif #ifndef ASSIMP_BUILD_NO_EXPORT #include "cexport.h" #include +//wangyi 0608 +#include namespace Assimp { - + class ExporterPimpl; class IOSystem; class ProgressHandler; @@ -84,7 +86,7 @@ class ASSIMP_API ExportProperties; class ASSIMP_API Exporter { public: /** Function pointer type of a Export worker function */ - typedef void (*fpExportFunc)(const char*, IOSystem*, const aiScene*, const ExportProperties*); + typedef void (*fpExportFunc)(const char *, IOSystem *, const aiScene *, const ExportProperties *); /** Internal description of an Assimp export format option */ struct ExportFormatEntry { @@ -98,8 +100,7 @@ public: unsigned int mEnforcePP; // Constructor to fill all entries - ExportFormatEntry( const char* pId, const char* pDesc, const char* pExtension, fpExportFunc pFunction, unsigned int pEnforcePP = 0u) - { + ExportFormatEntry(const char *pId, const char *pDesc, const char *pExtension, fpExportFunc pFunction, unsigned int pEnforcePP = 0u) { mDescription.id = pId; mDescription.description = pDesc; mDescription.fileExtension = pExtension; @@ -108,9 +109,8 @@ public: } ExportFormatEntry() : - mExportFunction() - , mEnforcePP() - { + mExportFunction(), + mEnforcePP() { mDescription.id = NULL; mDescription.description = NULL; mDescription.fileExtension = NULL; @@ -142,7 +142,7 @@ public: * * @param pIOHandler The IO handler to be used in all file accesses * of the Importer. */ - void SetIOHandler( IOSystem* pIOHandler); + void SetIOHandler(IOSystem *pIOHandler); // ------------------------------------------------------------------- /** Retrieves the IO handler that is currently set. @@ -151,7 +151,7 @@ public: * handler is active as long the application doesn't supply its own * custom IO handler via #SetIOHandler(). * @return A valid IOSystem interface, never NULL. */ - IOSystem* GetIOHandler() const; + IOSystem *GetIOHandler() const; // ------------------------------------------------------------------- /** Checks whether a default IO handler is active @@ -171,7 +171,7 @@ public: * disable progress reporting. * @note Progress handlers can be used to abort the loading * at almost any time.*/ - void SetProgressHandler(ProgressHandler* pHandler); + void SetProgressHandler(ProgressHandler *pHandler); // ------------------------------------------------------------------- /** Exports the given scene to a chosen file format. Returns the exported @@ -191,10 +191,10 @@ public: * Any IO handlers set via #SetIOHandler are ignored here. * @note Use aiCopyScene() to get a modifiable copy of a previously * imported scene. */ - const aiExportDataBlob* ExportToBlob(const aiScene* pScene, const char* pFormatId, - unsigned int pPreprocessing = 0u, const ExportProperties* pProperties = nullptr); - const aiExportDataBlob* ExportToBlob( const aiScene* pScene, const std::string& pFormatId, - unsigned int pPreprocessing = 0u, const ExportProperties* pProperties = nullptr); + const aiExportDataBlob *ExportToBlob(const aiScene *pScene, const char *pFormatId, + unsigned int pPreprocessing = 0u, const ExportProperties *pProperties = nullptr); + const aiExportDataBlob *ExportToBlob(const aiScene *pScene, const std::string &pFormatId, + unsigned int pPreprocessing = 0u, const ExportProperties *pProperties = nullptr); // ------------------------------------------------------------------- /** Convenience function to export directly to a file. Use @@ -229,10 +229,10 @@ public: * @return AI_SUCCESS if everything was fine. * @note Use aiCopyScene() to get a modifiable copy of a previously * imported scene.*/ - aiReturn Export( const aiScene* pScene, const char* pFormatId, const char* pPath, - unsigned int pPreprocessing = 0u, const ExportProperties* pProperties = nullptr); - aiReturn Export( const aiScene* pScene, const std::string& pFormatId, const std::string& pPath, - unsigned int pPreprocessing = 0u, const ExportProperties* pProperties = nullptr); + aiReturn Export(const aiScene *pScene, const char *pFormatId, const char *pPath, + unsigned int pPreprocessing = 0u, const ExportProperties *pProperties = nullptr); + aiReturn Export(const aiScene *pScene, const std::string &pFormatId, const std::string &pPath, + unsigned int pPreprocessing = 0u, const ExportProperties *pProperties = nullptr); // ------------------------------------------------------------------- /** Returns an error description of an error that occurred in #Export @@ -244,17 +244,17 @@ public: * * @note The returned function remains valid until one of the * following methods is called: #Export, #ExportToBlob, #FreeBlob */ - const char* GetErrorString() const; + const char *GetErrorString() const; // ------------------------------------------------------------------- /** Return the blob obtained from the last call to #ExportToBlob */ - const aiExportDataBlob* GetBlob() const; + const aiExportDataBlob *GetBlob() const; // ------------------------------------------------------------------- /** Orphan the blob from the last call to #ExportToBlob. This means * the caller takes ownership and is thus responsible for calling * the C API function #aiReleaseExportBlob to release it. */ - const aiExportDataBlob* GetOrphanedBlob() const; + const aiExportDataBlob *GetOrphanedBlob() const; // ------------------------------------------------------------------- /** Frees the current blob. @@ -264,7 +264,7 @@ public: * automatically by the destructor. The only reason to call * it manually would be to reclaim as much storage as possible * without giving up the #Exporter instance yet. */ - void FreeBlob( ); + void FreeBlob(); // ------------------------------------------------------------------- /** Returns the number of export file formats available in the current @@ -290,7 +290,7 @@ public: * for. Valid range is 0 to #Exporter::GetExportFormatCount * @return A description of that specific export format. * NULL if pIndex is out of range. */ - const aiExportFormatDesc* GetExportFormatDescription( size_t pIndex ) const; + const aiExportFormatDesc *GetExportFormatDescription(size_t pIndex) const; // ------------------------------------------------------------------- /** Register a custom exporter. Custom export formats are limited to @@ -303,7 +303,7 @@ public: * registered. A common cause that would prevent an exporter * from being registered is that its format id is already * occupied by another format. */ - aiReturn RegisterExporter(const ExportFormatEntry& desc); + aiReturn RegisterExporter(const ExportFormatEntry &desc); // ------------------------------------------------------------------- /** Remove an export format previously registered with #RegisterExporter @@ -314,11 +314,11 @@ public: * 'id' field of #aiExportFormatDesc. * @note Calling this method on a format description not yet registered * has no effect.*/ - void UnregisterExporter(const char* id); + void UnregisterExporter(const char *id); protected: // Just because we don't want you to know how we're hacking around. - ExporterPimpl* pimpl; + ExporterPimpl *pimpl; }; class ASSIMP_API ExportProperties { @@ -332,6 +332,8 @@ public: typedef std::map FloatPropertyMap; typedef std::map StringPropertyMap; typedef std::map MatrixPropertyMap; + //wangyi 0608 + typedef std::map> CallbackPropertyMap; public: /** Standard constructor @@ -345,7 +347,7 @@ public: * This copies the configuration properties of another ExportProperties. * @see ExportProperties(const ExportProperties& other) */ - ExportProperties(const ExportProperties& other); + ExportProperties(const ExportProperties &other); // ------------------------------------------------------------------- /** Set an integer configuration property. @@ -360,7 +362,7 @@ public: * floating-point property has no effect - the loader will call * GetPropertyFloat() to read the property, but it won't be there. */ - bool SetPropertyInteger(const char* szName, int iValue); + bool SetPropertyInteger(const char *szName, int iValue); // ------------------------------------------------------------------- /** Set a boolean configuration property. Boolean properties @@ -369,27 +371,30 @@ public: * #GetPropertyBool and vice versa. * @see SetPropertyInteger() */ - bool SetPropertyBool(const char* szName, bool value) { - return SetPropertyInteger(szName,value); + bool SetPropertyBool(const char *szName, bool value) { + return SetPropertyInteger(szName, value); } // ------------------------------------------------------------------- /** Set a floating-point configuration property. * @see SetPropertyInteger() */ - bool SetPropertyFloat(const char* szName, ai_real fValue); + bool SetPropertyFloat(const char *szName, ai_real fValue); // ------------------------------------------------------------------- /** Set a string configuration property. * @see SetPropertyInteger() */ - bool SetPropertyString(const char* szName, const std::string& sValue); + bool SetPropertyString(const char *szName, const std::string &sValue); // ------------------------------------------------------------------- /** Set a matrix configuration property. * @see SetPropertyInteger() */ - bool SetPropertyMatrix(const char* szName, const aiMatrix4x4& sValue); + bool SetPropertyMatrix(const char *szName, const aiMatrix4x4 &sValue); + + //wangyi 0608 + bool SetPropertyCallback(const char *szName, std::function &f); // ------------------------------------------------------------------- /** Get a configuration property. @@ -404,8 +409,8 @@ public: * floating-point property has no effect - the loader will call * GetPropertyFloat() to read the property, but it won't be there. */ - int GetPropertyInteger(const char* szName, - int iErrorReturn = 0xffffffff) const; + int GetPropertyInteger(const char *szName, + int iErrorReturn = 0xffffffff) const; // ------------------------------------------------------------------- /** Get a boolean configuration property. Boolean properties @@ -414,16 +419,16 @@ public: * #GetPropertyBool and vice versa. * @see GetPropertyInteger() */ - bool GetPropertyBool(const char* szName, bool bErrorReturn = false) const { - return GetPropertyInteger(szName,bErrorReturn)!=0; + bool GetPropertyBool(const char *szName, bool bErrorReturn = false) const { + return GetPropertyInteger(szName, bErrorReturn) != 0; } // ------------------------------------------------------------------- /** Get a floating-point configuration property * @see GetPropertyInteger() */ - ai_real GetPropertyFloat(const char* szName, - ai_real fErrorReturn = 10e10f) const; + ai_real GetPropertyFloat(const char *szName, + ai_real fErrorReturn = 10e10f) const; // ------------------------------------------------------------------- /** Get a string configuration property @@ -431,8 +436,8 @@ public: * The return value remains valid until the property is modified. * @see GetPropertyInteger() */ - const std::string GetPropertyString(const char* szName, - const std::string& sErrorReturn = "") const; + const std::string GetPropertyString(const char *szName, + const std::string &sErrorReturn = "") const; // ------------------------------------------------------------------- /** Get a matrix configuration property @@ -440,37 +445,42 @@ public: * The return value remains valid until the property is modified. * @see GetPropertyInteger() */ - const aiMatrix4x4 GetPropertyMatrix(const char* szName, - const aiMatrix4x4& sErrorReturn = aiMatrix4x4()) const; + const aiMatrix4x4 GetPropertyMatrix(const char *szName, + const aiMatrix4x4 &sErrorReturn = aiMatrix4x4()) const; - // ------------------------------------------------------------------- - /** Determine a integer configuration property has been set. + //wangyi 0608 + std::function GetPropertyCallback(const char* szName) const; + + // ------------------------------------------------------------------- + /** Determine a integer configuration property has been set. * @see HasPropertyInteger() */ - bool HasPropertyInteger(const char* szName) const; + bool HasPropertyInteger(const char *szName) const; /** Determine a boolean configuration property has been set. * @see HasPropertyBool() */ - bool HasPropertyBool(const char* szName) const; + bool HasPropertyBool(const char *szName) const; /** Determine a boolean configuration property has been set. * @see HasPropertyFloat() */ - bool HasPropertyFloat(const char* szName) const; + bool HasPropertyFloat(const char *szName) const; /** Determine a String configuration property has been set. * @see HasPropertyString() */ - bool HasPropertyString(const char* szName) const; + bool HasPropertyString(const char *szName) const; /** Determine a Matrix configuration property has been set. * @see HasPropertyMatrix() */ - bool HasPropertyMatrix(const char* szName) const; + bool HasPropertyMatrix(const char *szName) const; + + //wangyi 0608 + bool HasPropertyCallback(const char *szName) const; protected: - /** List of integer properties */ IntPropertyMap mIntProperties; @@ -482,23 +492,22 @@ protected: /** List of Matrix properties */ MatrixPropertyMap mMatrixProperties; + + //wangyi 0608 + CallbackPropertyMap mCallbackProperties; }; // ---------------------------------------------------------------------------------- -inline -const aiExportDataBlob* Exporter::ExportToBlob( const aiScene* pScene, const std::string& pFormatId, - unsigned int pPreprocessing, const ExportProperties* pProperties) -{ - return ExportToBlob(pScene,pFormatId.c_str(),pPreprocessing, pProperties); +inline const aiExportDataBlob *Exporter::ExportToBlob(const aiScene *pScene, const std::string &pFormatId, + unsigned int pPreprocessing, const ExportProperties *pProperties) { + return ExportToBlob(pScene, pFormatId.c_str(), pPreprocessing, pProperties); } // ---------------------------------------------------------------------------------- -inline -aiReturn Exporter :: Export( const aiScene* pScene, const std::string& pFormatId, - const std::string& pPath, unsigned int pPreprocessing, - const ExportProperties* pProperties) -{ - return Export(pScene,pFormatId.c_str(),pPath.c_str(),pPreprocessing, pProperties); +inline aiReturn Exporter ::Export(const aiScene *pScene, const std::string &pFormatId, + const std::string &pPath, unsigned int pPreprocessing, + const ExportProperties *pProperties) { + return Export(pScene, pFormatId.c_str(), pPath.c_str(), pPreprocessing, pProperties); } } // namespace Assimp From f57e7221c07f385cebcc457d294e90c446995d41 Mon Sep 17 00:00:00 2001 From: ywang Date: Wed, 10 Jun 2020 13:23:29 -0700 Subject: [PATCH 27/62] temp --- code/AssetLib/glTF2/glTF2Exporter.cpp | 17 +++++++++++++++-- code/Common/Exporter.cpp | 2 +- include/assimp/Exporter.hpp | 2 +- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/code/AssetLib/glTF2/glTF2Exporter.cpp b/code/AssetLib/glTF2/glTF2Exporter.cpp index 566f95e80..98eb79e57 100644 --- a/code/AssetLib/glTF2/glTF2Exporter.cpp +++ b/code/AssetLib/glTF2/glTF2Exporter.cpp @@ -1,4 +1,4 @@ -/* +/* Open Asset Import Library (assimp) ---------------------------------------------------------------------- @@ -115,7 +115,20 @@ glTF2Exporter::glTF2Exporter(const char* filename, IOSystem* pIOSystem, const ai ExportScene(); ExportAnimations(); - + + //wangyi 0608 + if(mProperties->HasPropertyCallback("extras")) + { + std::function ExportExtras = mProperties->GetPropertyCallback("extras"); + char* ret = (char*)ExportExtras((void*)mAsset.get()); + + Document extrasD; + extrasD.Parse(ret); + std::string strHello = extrasD["hello"].GetString(); + + printf("wangyi 0608 ret: %s\r\n", ret); + } + AssetWriter writer(*mAsset); if (isBinary) { diff --git a/code/Common/Exporter.cpp b/code/Common/Exporter.cpp index e8ee188e6..5fef455bb 100644 --- a/code/Common/Exporter.cpp +++ b/code/Common/Exporter.cpp @@ -587,7 +587,7 @@ ExportProperties::ExportProperties(const ExportProperties &other) } //wangyi 0608 -bool ExportProperties::SetPropertyCallback(const char *szName, std::function &f) { +bool ExportProperties::SetPropertyCallback(const char *szName, const std::function &f) { return SetGenericProperty>(mCallbackProperties, szName, f); } std::function ExportProperties::GetPropertyCallback(const char *szName) const { diff --git a/include/assimp/Exporter.hpp b/include/assimp/Exporter.hpp index 4abea6ad0..87c12f374 100644 --- a/include/assimp/Exporter.hpp +++ b/include/assimp/Exporter.hpp @@ -394,7 +394,7 @@ public: bool SetPropertyMatrix(const char *szName, const aiMatrix4x4 &sValue); //wangyi 0608 - bool SetPropertyCallback(const char *szName, std::function &f); + bool SetPropertyCallback(const char *szName, const std::function &f); // ------------------------------------------------------------------- /** Get a configuration property. From e65434bf8241a5408ff213dc315d5b8d3ed2f60e Mon Sep 17 00:00:00 2001 From: ywang Date: Thu, 11 Jun 2020 17:37:06 -0700 Subject: [PATCH 28/62] extra callback --- code/AssetLib/glTF2/glTF2Asset.h | 3 ++- code/AssetLib/glTF2/glTF2AssetWriter.inl | 6 +++++- code/AssetLib/glTF2/glTF2Exporter.cpp | 10 ++-------- code/Common/Exporter.cpp | 5 ++--- include/assimp/Exporter.hpp | 12 +++--------- 5 files changed, 14 insertions(+), 22 deletions(-) diff --git a/code/AssetLib/glTF2/glTF2Asset.h b/code/AssetLib/glTF2/glTF2Asset.h index fc0fe1544..de252b329 100644 --- a/code/AssetLib/glTF2/glTF2Asset.h +++ b/code/AssetLib/glTF2/glTF2Asset.h @@ -1,4 +1,4 @@ -/* +/* Open Asset Import Library (assimp) ---------------------------------------------------------------------- @@ -1006,6 +1006,7 @@ public: } extensionsRequired; AssetMetadata asset; + Value* extras = nullptr; // Dictionaries for each type of object diff --git a/code/AssetLib/glTF2/glTF2AssetWriter.inl b/code/AssetLib/glTF2/glTF2AssetWriter.inl index 361af40cd..0a4d0b2f4 100644 --- a/code/AssetLib/glTF2/glTF2AssetWriter.inl +++ b/code/AssetLib/glTF2/glTF2AssetWriter.inl @@ -1,4 +1,4 @@ -/* +/* Open Asset Import Library (assimp) ---------------------------------------------------------------------- @@ -600,6 +600,10 @@ namespace glTF2 { if (mAsset.scene) { mDoc.AddMember("scene", mAsset.scene->index, mAl); } + + if(mAsset.extras) { + mDoc.AddMember("extras", *mAsset.extras, mAl); + } } inline void AssetWriter::WriteFile(const char* path) diff --git a/code/AssetLib/glTF2/glTF2Exporter.cpp b/code/AssetLib/glTF2/glTF2Exporter.cpp index 98eb79e57..537787eb7 100644 --- a/code/AssetLib/glTF2/glTF2Exporter.cpp +++ b/code/AssetLib/glTF2/glTF2Exporter.cpp @@ -116,17 +116,11 @@ glTF2Exporter::glTF2Exporter(const char* filename, IOSystem* pIOSystem, const ai ExportAnimations(); - //wangyi 0608 + // export extras if(mProperties->HasPropertyCallback("extras")) { std::function ExportExtras = mProperties->GetPropertyCallback("extras"); - char* ret = (char*)ExportExtras((void*)mAsset.get()); - - Document extrasD; - extrasD.Parse(ret); - std::string strHello = extrasD["hello"].GetString(); - - printf("wangyi 0608 ret: %s\r\n", ret); + mAsset->extras = (rapidjson::Value*)ExportExtras(0); } AssetWriter writer(*mAsset); diff --git a/code/Common/Exporter.cpp b/code/Common/Exporter.cpp index 5fef455bb..30ab3a813 100644 --- a/code/Common/Exporter.cpp +++ b/code/Common/Exporter.cpp @@ -581,19 +581,18 @@ ExportProperties::ExportProperties(const ExportProperties &other) , mFloatProperties(other.mFloatProperties) , mStringProperties(other.mStringProperties) , mMatrixProperties(other.mMatrixProperties) -//wangyi 0608 , mCallbackProperties(other.mCallbackProperties){ // empty } -//wangyi 0608 bool ExportProperties::SetPropertyCallback(const char *szName, const std::function &f) { return SetGenericProperty>(mCallbackProperties, szName, f); } + std::function ExportProperties::GetPropertyCallback(const char *szName) const { return GetGenericProperty>(mCallbackProperties, szName, 0); } -//wangyi 0608 + bool ExportProperties::HasPropertyCallback(const char *szName) const { return HasGenericProperty>(mCallbackProperties, szName); } diff --git a/include/assimp/Exporter.hpp b/include/assimp/Exporter.hpp index 87c12f374..8e47e24db 100644 --- a/include/assimp/Exporter.hpp +++ b/include/assimp/Exporter.hpp @@ -54,7 +54,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "cexport.h" #include -//wangyi 0608 #include namespace Assimp { @@ -332,7 +331,6 @@ public: typedef std::map FloatPropertyMap; typedef std::map StringPropertyMap; typedef std::map MatrixPropertyMap; - //wangyi 0608 typedef std::map> CallbackPropertyMap; public: @@ -392,8 +390,7 @@ public: * @see SetPropertyInteger() */ bool SetPropertyMatrix(const char *szName, const aiMatrix4x4 &sValue); - - //wangyi 0608 + bool SetPropertyCallback(const char *szName, const std::function &f); // ------------------------------------------------------------------- @@ -448,7 +445,6 @@ public: const aiMatrix4x4 GetPropertyMatrix(const char *szName, const aiMatrix4x4 &sErrorReturn = aiMatrix4x4()) const; - //wangyi 0608 std::function GetPropertyCallback(const char* szName) const; // ------------------------------------------------------------------- @@ -476,8 +472,7 @@ public: * @see HasPropertyMatrix() */ bool HasPropertyMatrix(const char *szName) const; - - //wangyi 0608 + bool HasPropertyCallback(const char *szName) const; protected: @@ -492,8 +487,7 @@ protected: /** List of Matrix properties */ MatrixPropertyMap mMatrixProperties; - - //wangyi 0608 + CallbackPropertyMap mCallbackProperties; }; From 1b0b4d8d1a33f46e9edfca0b9f1758e194c68d28 Mon Sep 17 00:00:00 2001 From: kimkulling Date: Fri, 12 Jun 2020 11:43:31 +0200 Subject: [PATCH 29/62] add a unittest. --- .../glTF2/issue_3269/texcoord_crash.gltf | 610 ++++++++++++++++++ test/unit/utglTF2ImportExport.cpp | 6 + 2 files changed, 616 insertions(+) create mode 100644 test/models/glTF2/issue_3269/texcoord_crash.gltf diff --git a/test/models/glTF2/issue_3269/texcoord_crash.gltf b/test/models/glTF2/issue_3269/texcoord_crash.gltf new file mode 100644 index 000000000..bc5d13f31 --- /dev/null +++ b/test/models/glTF2/issue_3269/texcoord_crash.gltf @@ -0,0 +1,610 @@ +{ + "accessors" : [ + { + "bufferView" : 0, + "componentType" : 5121, + "count" : 6, + "max" : [ + 3 + ], + "min" : [ + 0 + ], + "type" : "SCALAR" + }, + { + "bufferView" : 1, + "componentType" : 5126, + "count" : 4, + "max" : [ + 1.2000000476837158, + 1.2000001668930054, + -5.205485820169997e-08 + ], + "min" : [ + 0.19999980926513672, + 0.20000004768371582, + -1.5933926533762133e-07 + ], + "type" : "VEC3" + }, + { + "bufferView" : 2, + "componentType" : 5126, + "count" : 4, + "max" : [ + -2.1316282072803006e-14, + 1.0728441424134871e-07, + 1.0 + ], + "min" : [ + -2.1316282072803006e-14, + 1.0728441424134871e-07, + 1.0 + ], + "type" : "VEC3" + }, + { + "name": "TopRight_TEXCOORD_0", + "bufferView" : 3, + "componentType" : 5126, + "count" : 4, + "max" : [ + 1.0, + 0.3999999761581421 + ], + "min" : [ + 0.6000000238418579, + 0.0 + ], + "type" : "VEC2" + }, + { + "bufferView" : 4, + "componentType" : 5121, + "count" : 6, + "max" : [ + 3 + ], + "min" : [ + 0 + ], + "type" : "SCALAR" + }, + { + "bufferView" : 5, + "componentType" : 5126, + "count" : 4, + "max" : [ + -0.20000006258487701, + 1.2000000476837158, + 1.2601539367551595e-07 + ], + "min" : [ + -1.2000001668930054, + 0.19999974966049194, + -3.3740951721483725e-07 + ], + "type" : "VEC3" + }, + { + "bufferView" : 6, + "componentType" : 5126, + "count" : 4, + "max" : [ + 1.7807019503379706e-07, + 2.853547016457014e-07, + 1.0 + ], + "min" : [ + 1.7807019503379706e-07, + 2.853547016457014e-07, + 1.0 + ], + "type" : "VEC3" + }, + { + "name": "TopLeft_TEXCOORD_0", + "bufferView" : 7, + "componentType" : 5126, + "count" : 4, + "max" : [ + 0.3999999463558197, + 0.3999999761581421 + ], + "min" : [ + 7.915305388905836e-08, + 0.0 + ], + "type" : "VEC2" + }, + { + "bufferView" : 8, + "componentType" : 5121, + "count" : 6, + "max" : [ + 3 + ], + "min" : [ + 0 + ], + "type" : "SCALAR" + }, + { + "bufferView" : 9, + "componentType" : 5126, + "count" : 4, + "max" : [ + 1.2000001668930054, + -0.1999996304512024, + 5.255118367131217e-07 + ], + "min" : [ + 0.2000000923871994, + -1.2000000476837158, + 6.20869826661874e-08 + ], + "type" : "VEC3" + }, + { + "bufferView" : 10, + "componentType" : 5126, + "count" : 4, + "max" : [ + -1.7807025187721592e-07, + 2.853545879588637e-07, + 1.0 + ], + "min" : [ + -1.7807025187721592e-07, + 2.853545879588637e-07, + 1.0 + ], + "type" : "VEC3" + }, + { + "name": "BottomRight_TEXCOORD_0", + "bufferView" : 11, + "componentType" : 5126, + "count" : 4, + "max" : [ + 0.9999998807907104, + 1.0 + ], + "min" : [ + 0.6000000834465027, + 0.599999874830246 + ], + "type" : "VEC2" + }, + { + "bufferView" : 12, + "componentType" : 5121, + "count" : 6, + "max" : [ + 3 + ], + "min" : [ + 0 + ], + "type" : "SCALAR" + }, + { + "bufferView" : 13, + "componentType" : 5126, + "count" : 4, + "max" : [ + 1.0000001192092896, + 1.0000001192092896, + -0.052591003477573395 + ], + "min" : [ + -1.0000001192092896, + -1.0000001192092896, + -0.05259115248918533 + ], + "type" : "VEC3" + }, + { + "bufferView" : 14, + "componentType" : 5126, + "count" : 4, + "max" : [ + 1.0658142730467397e-14, + -7.450581307466564e-08, + -1.0 + ], + "min" : [ + 1.0658142730467397e-14, + -7.450581307466564e-08, + -1.0 + ], + "type" : "VEC3" + }, + { + "bufferView" : 15, + "componentType" : 5121, + "count" : 6, + "max" : [ + 3 + ], + "min" : [ + 0 + ], + "type" : "SCALAR" + }, + { + "bufferView" : 16, + "componentType" : 5126, + "count" : 4, + "max" : [ + -0.19999969005584717, + -0.2000000774860382, + 5.255118367131217e-07 + ], + "min" : [ + -1.2000000476837158, + -1.2000001668930054, + 6.208701108789683e-08 + ], + "type" : "VEC3" + }, + { + "bufferView" : 17, + "componentType" : 5126, + "count" : 4, + "max" : [ + -8.526512829121202e-14, + 4.6342486825778906e-07, + 1.0 + ], + "min" : [ + -8.526512829121202e-14, + 4.6342486825778906e-07, + 1.0 + ], + "type" : "VEC3" + }, + { + "name": "BottomLeft_TEXCOORD_0", + "bufferView" : 18, + "componentType" : 5126, + "count" : 4, + "max" : [ + 0.40000009536743164, + 0.9999999208469248 + ], + "min" : [ + 0.0, + 0.6000000536441803 + ], + "type" : "VEC2" + } + ], + "asset" : { + "copyright" : "Copyright 2017-2018 Analytical Graphics, Inc., CC-BY 4.0 https://creativecommons.org/licenses/by/4.0/ - Mesh and textures by Ed Mackey.", + "generator" : "Khronos Blender glTF 2.0 exporter, plus hand-edits", + "version" : "2.0" + }, + "bufferViews" : [ + { + "buffer" : 0, + "byteLength" : 6, + "byteOffset" : 0, + "target" : 34963 + }, + { + "buffer" : 0, + "byteLength" : 48, + "byteOffset" : 8, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 48, + "byteOffset" : 56, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 32, + "byteOffset" : 104, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 6, + "byteOffset" : 136, + "target" : 34963 + }, + { + "buffer" : 0, + "byteLength" : 48, + "byteOffset" : 144, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 48, + "byteOffset" : 192, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 32, + "byteOffset" : 240, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 6, + "byteOffset" : 272, + "target" : 34963 + }, + { + "buffer" : 0, + "byteLength" : 48, + "byteOffset" : 280, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 48, + "byteOffset" : 328, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 32, + "byteOffset" : 376, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 6, + "byteOffset" : 408, + "target" : 34963 + }, + { + "buffer" : 0, + "byteLength" : 48, + "byteOffset" : 416, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 48, + "byteOffset" : 464, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 6, + "byteOffset" : 512, + "target" : 34963 + }, + { + "buffer" : 0, + "byteLength" : 48, + "byteOffset" : 520, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 48, + "byteOffset" : 568, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 32, + "byteOffset" : 616, + "target" : 34962 + } + ], + "buffers" : [ + { + "byteLength" : 648, + "uri" : "data:application/octet-stream;base64,AAECAwEAAACamZk/2sxMPuySX7PAzEw+mZmZP9gWK7TKzEw+0MxMPuySX7OYmZk/m5mZP9gWK7QAAMCoO2TmMwAAgD8AAMCoO2TmMwAAgD8AAMCoO2TmMwAAgD8AAMCoO2TmMwAAgD8AAIA/zMzMPpqZGT8AAAAAmpkZP8zMzD4AAIA/AAAAAAABAgMBAAAA0cxMvsnMTD7okl+zm5mZv5iZmT/aFiu0mZmZv7zMTD7ZTgc03sxMvpqZmT82JbW0kDM/NNoymTQAAIA/kDM/NNoymTQAAIA/kDM/NNoymTQAAIA/kDM/NNoymTQAAIA/y8zMPszMzD7a+qkzAAAAANr6qTPMzMw+y8zMPgAAAAAAAQIDAQAAAJuZmT+YmZm/5hANNdPMTD7HzEy+rlSFM+bMTD6amZm/Boi6NJmZmT+0zEy+8u6ANJQzP7TWMpk0AACAP5QzP7TWMpk0AACAP5QzP7TWMpk0AACAP5QzP7TWMpk0AACAP/3/fz8AAIA/m5kZP5iZGT+cmRk/AACAP/7/fz+YmRk/AAECAAMBAAABAIC//f9/P9JpV70BAIA//f9/v6ppV739/3+/AQCAv6ppV739/38/AQCAP9JpV70CAEAoAQCgswAAgL8CAEAoAQCgswAAgL8CAEAoAQCgswAAgL8CAEAoAQCgswAAgL8AAQIDAQAAALjMTL6ZmZm/5hANNZqZmb/izEy+uFSFM5iZmb+bmZm/5hANNcjMTL7SzEy+slSFMwAAwKmhzPg0AACAPwAAwKmhzPg0AACAPwAAwKmhzPg0AACAPwAAwKmhzPg0AACAP9DMzD7//38/AACAM5qZGT8AAAAA//9/P83MzD6amRk/" + } + ], + "images" : [ + { + "uri" : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAgAAAAIACAYAAAD0eNT6AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4QYcDhkW4QlOQwAAHBNJREFUeNrt3XuMlNX9P/DP4u7OLkshVEGkgKyVWzTNsloTbYtGaIgmRGM1tRq1TbVSaqm2qdREwbSJoQlQGm9NiNSmCSyRRhNtm0YTTUyq1jWhtFDF2lKrqcKuCsJegfP74/vbDbC3mZ2Zvcy8Xslkk5lnn3l2zjPn8z7nuWxFSikFAFBWJvgIAEAAAAAEAABAAAAABAAAQAAAAAQAAEAAAAAEAABg9FRmu2BFRUVWy7mxIAAUXqHrcOVY/kOECQBKvWiPVq2rLPUPV4gAQH0pwQBQzAYWHgD08aWq0u5R2J1KaADQ7woADLrj2mkBfaO+UQCg3y+DLwKgP0MA4JQvlC8ToE9iuNwIqIS+hNleIwqgn0EAKPFU7ssK6EPot41TgedsCnmnokLcQCGf6ziHc/lILmepZnPyy2DH0Pqbeut5LqUUFRUVpuSAvPrznr6kv35msD4pm/4sl75xOP1uPn18IepLIWtdtusyA0BRdhZAH0LpcBKgLyyAfkUAwJcSQN8jAOCLBqC/EgDwZQHQ5wkA2MEB9KMCgJ0QAH21AGDHAEB9EAA0DgACxDgNAIW66xEAkFvdLHQNdidAAChDAgAACAAAgAAAAAgAAIAAAAAIAACAAAAAjFk53QgomxsMuFkQAORmNGqnGQAAKEMCAAAIAACAAAAACAAAgAAAAAgAAIAAAACMWZW5/sJQNytwkx8AyE0hbrSXa/01AwAAZUgAAAABAAAQAAAAAQAASklFRUVW/4lPAGDEHTt2LNatWxf19fWRyWRizpw5PhQg74KX7WO0ty+TycTnPve5uP7666O5uXlUC3iphYWKlON1A6N9GWCuH/5IX5bYs32Fet/169fHfffd1+dvKvT7AOUTAMZDH9qfqqqqeOaZZ+Lqq68uWJ+by++Pdr876pcBppQGfYy1NDnePfnkkxERsXXr1ujo6FDwgbz0129n89pobWdHR0f8/e9/j69//evR3d3d74CoVPrFoernUPU3VxPsvGPb/v37o6qqKr75zW9GJpPRewEjpru7OzZt2hSNjY1RV1cXdXV10djYGJs3b45jx471W7w+/PDDWLlyZcyYMSNqa2vjS1/6Urz22mvD3oZMJhMXXHBBPPLIIxERsW/fvn7f92Tt7e2xdu3aqK+vj6qqqpg7d2488MADMWnSpAEHou+++27ceuutMXXq1JgxY0bcdddd0dHR0e/ou2QGtqnAImLQRzEMtO6urq60cePGtHjx4jRx4sQ0ceLEtHjx4vSLX/widXd397uODz74IN15553p7LPPTjU1Nemyyy5Lr776at7bcrqdO3emZcuWpalTp6aqqqp07rnnptWrV6eWlpZBP8uhPmOAQvShXV1dadmyZQP2NcuXLz+lH+15fsqUKX2WraurS2+//XZefeg//vGPFBGpvr5+0OW7urrSV77ylaz7yZ7nzjzzzD7LrVu3LqvaNl7rZ8kGgLG2857sjjvuGHC75s+fnz755BMBABjVALBhw4YUEWn69OmpqakptbS0pJaWlrRt27Y0bdq0FBFp06ZNfdZx/fXXp1dffTW1t7en3bt3p8bGxhQR6dvf/vawtuXQoUPpxRdf7F3P2rVrB13+l7/8Ze92P/300+nw4cPp4MGDaefOnYMGgMsvvzzt2rUrHTp0KK1ZsyZFRJo3b96wBngCwCgHgLGy857uySefTBGRZs2alXbs2JEOHDiQ2traUnNzc7riiitSRKT77rtvyPUp+EAx+9CGhoYUEempp57qs3xTU1OKiLR48eIh+6SXX36535H7cGrIddddlzo6Ogbd9osvvjhFRNq+fXtWf2fPc8ePH+997sMPP0wRkTKZjAAwHgPAaO+8A7n00ktTRKTm5uY+r/33v/9NEZEWLVokAACjGgBqa2tTRKTW1tY+y7e0tKSISBMnThyyT/r0009TRKTq6uq8asj69euz2va6uroUEengwYM5BYCTdXd3Z73seK6fJXsfgLfeeisiIq688so+ry1btuyUZQbT0NAQERHvv/9+QbZr9+7dERFx8cUX9zmRZPbs2RER8e9//9vZR8CYOfE6m+cG0nMiXVVV1bBO+H700UcjImLz5s2xf//+IX+vq6srIiJqa2uH/TdXVlaWRdtOsPMWZ+cdyIkTJ7J+T4DRMn/+/IiIeP755/u89sILL0RExIIFC4Zcz0svvRQREYsWLRrWdqxatSruueee+OCDD+Kqq66Kjz76aNDlZ86cecpgqxg6OzvLNwCM5HWK433nPd3ChQsjIuKdd94pyOdUKjsiMLbccsstERGxevXqaGpqitbW1mhtbY2mpqZYvXr1Kcuc7Pe//3188sknceTIkXjuued6l73pppuGvS0bNmyIa6+9Nt5888245pprBu33emZ977777tizZ08cPXo0mpub47bbbsv7M+kJFw899FC0tbUVZcCahnmfneG+YUGPU4y1M1inTZuWtm/f3nsS4Pbt2wc9CfC5555LH3/8cfr000/Ts88+m84555w+y+ZzDsBjjz2WIiLNnj07PfHEE+k///lPam9vT21tbWnPnj3p0UcfTRdddNGQ65s5c2bvGbFHjx51EBMoaB/a1dWVli5dmvOVVP09LrvsstTZ2ZlXH3r06NHeE/xuuOGGdOLEiX6X37dvX5o0aVKfbaiurs7puH5/z69cuXJU616ha2/JBoDR3nkHehw/fjx961vfyvpkj4E+19HeEYHSDgA9/ejGjRtTQ0NDqq2tTbW1tamhoSFt2rRpwHuprFmzJn3+859PmUwmzZo1K/34xz9OR44cyXtbUkrpf//7X5ozZ06KiHT33XcPuPzrr7+elixZkmpqatLkyZPTihUr0htvvJEiItXU1Aw7ABw5ciTde++96bzzzkuZTCZNmTIlXXLJJeM2AOT8vwB6DgHkcsy92Aa6P3N3d3c8/PDD8dvf/rb3hL8FCxbErbfeGt///vdPOdGjZx1r1qyJnTt3xnvvvRfTpk2Lb3zjG7Fu3bqoq6vL+7M5eRv/+Mc/xhNPPBGvvfZaHDhwICoqKqK+vj6WLl0aN954Y3z5y18e9G87evRo/PSnP42dO3fG+++/HzU1NbFgwYK87rgFUOh+eKzYs2dPXHjhhTFv3rw+dxMcb59xoWpvSQSActh5AfShuevu7o69e/fGqlWr4s9//nPcdddd8fDDDwsAAoAAAFBqfehANWrGjBnxxhtv9J7MV+4BYILdFoBSsmLFipg9e3bU1tZGdXV1zJ07N+688854/fXXx23xL0qgSAWOa+N1dsAMAAClNsofTKWPe+yHEwAoNIcAAEAAAAAEAABAAAAABAAAYJwa9lUAA12q4Gx6ABiewWpooeuuGQAAKEMCAAAIAACAAAAACAAAQGkY9lUAA5116OoAABi+kaqjZgAAoAwJAAAgAAAAAgAAIAAAAKWhMp9f7u9MRWf7A8Dw5XKVXT411wwAAJQhAQAABAAAQAAAAEpSXicB9nfygRMDASA/I1FLzQAAQBkSAABAAAAABAAAoCRV5ruC009UcMIfAOQnm5Ps8623ZgAAoAwJAAAgAAAA5SDvcwBOPwbhnAAAyF+x66kZAAAoQwIAAAgAAEA5qCzESk4+TuGYPwDkb7Bz7ApRa80AAEAZEgAAoAwV5BDAyVMRDgcAQGEUs6aaAQCAMiQAAEAZqizUinqmKUz7A0Bh9HeIvVB11gwAAJgByD+lmAkAgMIpVl01AwAAZgDyTylG/gBQOCfPsBeyxk4o9Eae/u8LAYCxN8CeMNY3EADMAhR+gF2RVGwAKDtOAgQAAQAAEAAAAAEAABAAAAABAAAQAAAAAQAAEAAAAAEAABAAAAABAAAQAAAAAQAAEAAAAAEAABAAAAABAAAEAABAAAAABAAAQAAAAAQAAEAAAAAEAABAAAAABAAAQAAAAAQAAEAAAAAEAABAAAAABAAAQAAAAAQAABAAAAABAAAQAAAAAQAAEAAAAAEAABAAAAABAAAQAAAAAQAAEAAAAAEAABAAAAABAAAQAAAAAQAAEAAAQAAAAAQAAEAAAAAEAABAAAAABAAAQAAAAAQAAEAAAAAEAABAAAAAiqTSRwBDq6io6Pf5lJIPR7uAGQAolwKT6zJoFxAAYBwVmWxGkiklxUa7gAAApSLbApJtQUK7gAAARppoFxAAwEgT7QICABhpol1AAAAjTbQLCABgpKldtAsIAGCkqV20CwgAYKSpXbQLCABgpKldAAEAjDS1CyAAgJGmdgEBAMpg5Jjrz1xHmrn+RLuAAABFLjI9BSHXn6O5bu2iXaBo379kjgyyHqX2N8pEu4AAAOOoSIwV5foV1C4wuhwCAAABAAAQAAAAAQAAEAAAgHHKVQCQzRfF5WbaBcwAwPgtFMW4M1wx161dtAsIAJCH4d4RLpdbzhZj3dpFu0DRArhDADD4KHKw28MqGtoFzABAiRaZbEeaaBcQAKAE+Lez2gUEADDSNNLULiAAgJGmkaZ2AQEAjDSNNLULCABgpIl2AQEAjDTRLiAAgJEm2gUEADDSRLuAAABGmmgXEADASBPtAgIAGGmiXUAAgBEpNoVYBu0CY43/BggAZgAAAAEAABAAAAABAAAQAAAAAQAAEAAAAAEAABAAAAABAAAQAAAAAQAAEAAAAAEAABAAAAABAAAQAABAAAAABAAAQAAAAAQAAEAAAAAEAABAAAAABAAAQAAAAAQAAEAAAAAEAABAAAAABAAAQAAAAAQAAEAAAAABAAAQAAAAAQAAEAAAAAEAABAAAAABAAAQAAAAAQAAEAAAAAEAABAAAAABAAAQAAAAAQAAEAAAAAEAAAQAAEAAAAAEAABAAAAABAAAQAAAAAQAAEAAAAAEAABAAAAARkaljwCGVlFR0e/zKSUfjnYBMwBQLgUm12XQLiAAwDgqMtmMJFNKio12AQEASkW2BSTbgoR2AQEAjDTRLiAAgJEm2gUEADDSRLuAAABGmmgXEADASFO7aBcQAMBIU7toFxAAwEhTu2gXEADASFO7AAIAGGlqF0AAACNN7QICAJTByDHXn7mONHP9iXYBAQCKXGR6CkKuP0dz3dpFu0DRvn/JHBlkPUrtb5SJdgEBAMZRkRgryvUrqF1gdDkEAAACAAAgAAAAAgAAIAAAAOOUqwAgmy+Ky820C5gBgPFbKIpxZ7hirlu7aBcQACAPw70jXC63nC3GurWLdoGiBXCHAGDwUeRgt4dVNLQLmAGAEi0y2Y400S4gAEAJ8G9ntQsIAGCkaaSpXUAAACNNI03tAgIAGGkaaWoXEADASBPtAgIAGGmiXUAAACNNtAsIAGCkiXYBAQCMNNEuIACAkSbaBQQAMNJEu4AAACNSbAqxDNoFxhr/DRAAzAAAAAIAACAAAAACAAAgAAAAAgAAIAAAAAIAACAAAAACAAAgAAAAAgAAIAAAAAIAACAAAAACAAAgAACAAAAACAAAgAAAAAgAAIAAAAAIAACAAAAACAAAgAAAAAgAAIAAAAAIAACAAAAACAAAgAAAAAgAAIAAAAACAAAgAAAAAgAAIAAAAAIAACAAAAACAAAgAAAAAgAAIAAAAAIAACAAAAACAAAgAAAAAgAAIAAAAAIAAAgAAIAAAAAIAACAAAAACAAAgAAAAAgAAIAAAAAIAACAAAAACAAAgAAAAIzJAFBRUeETBYAiKHSNLWgASCkJAQBQhOKfUhrbMwCF3kAAKHfFGGBXFmsDBQEAKMzguhh11UmAAFCGCjYDYOQPAIXXU1cLXWfNAACAGYDCJRSzAQCQn2LWVDMAAFCGBAAAKEMFOQRg2h8ACu/kmlroWmsGAADKkAAAAGWoIIcABpqiOP01ACA7xa6nZgAAoAwJAAAgAAAA5SDvcwAc8weAwju9nha63poBAIAyJAAAgAAAAJSDvM8BGOoYRX/LAAADG4laagYAAMqQAAAAAgAAIAAAACUpr5MAnfAHAIXXXy0tdM01AwAAZUgAAAABAAAQAACAkpTXSYDZnqQw0LIAwOjUUTMAAFCGBAAAEAAAAAFgDKqoqDjlUVNTE+eff3786Ec/ikOHDuW93lxfA0AfPS7bKhX4rIJin7wwWCNfc8018cwzz+S13sFObHQiI4A+erQ+wzFzEuDpKa/nkVLq91FoKaU4ceJEfPrpp/H4449HRMSf/vQn3z6AMUAfnd9n199joLo74gFgrKSkSZMmxc033xwREdOnTz/l9e7u7ti0aVM0NjZGXV1d1NXVRWNjY2zevDmOHTvWb9oa7MPt7/ls3+P0dezevTuuvfbamDx5ckyePDluuumm+Pjjj+Oll16K5cuXx2c+85mYMWNGrFy5Mtrb230jAH20PrrgSWNYIqLfR7Gd/j6HDx9O999/f4qItGXLlt7nu7q60rJlywbczuXLl6fu7u5B/5ahHrm8x+nbP2HChD7Lz507t9/13H///QlgPNBHF/+zLVTdHbcB4PRHY2Njev/993uX27BhQ4qINH369NTU1JRaWlpSS0tL2rZtW5o2bVqKiLRp06YBd9rBdujhvsfJ61qyZEnatWtX6ujoSA8++GC/z69duzZFRDr//PP1KsC4CgD6aAFgxD6AiEhTp05Nu3btSiml1NDQkCIiPfXUU33W0dTUlCIiLV68OK+dK9f3OHldx48f733uwIEDKSJSVVXVKc9/+OGHKSJSJpPRqwDjOgDoowWAgk8vdXV1pf3796fbb7+9d0onpZRqa2tTRKTW1tY+62hpaUkRkSZOnJjXzpXrewy0rmPHjuX0PMBYDwD66LEfACbkce5ATmcpFusazaqqqjj33HNj48aNERHx6quvDnnZRCrwVQn5vscZZ5yR0/MA44U+OvcTJ0fqKruSuRPg4cOHT2nU+fPnR0TE888/32fZF154ISIiFixY0Oe1zs7OAd/j9NeG+x4A5UYfPfaM+wDQ1dUVu3fvjttvvz0iIpYsWRIREbfccktERKxevTqampqitbU1Wltbo6mpKVavXn3KMhERM2fOjIiIhx56KNra2k55j4Fey/U9AMqNPnoMG8kTQIq9/smTJ6e//e1vvcedli5dmvXlHytXrhxwmwd6Ldf3GOxYVa7PA4y3kwD10aNfQwtyEuBYCQBnnHFGOuecc9LNN9+c3n777VOW7erqShs3bkwNDQ2ptrY21dbWpoaGhrRp06Y+jX7kyJF07733pvPOOy9lMpk0ZcqUdMkllwz5Wi7vIQAA5RYA9NFjNwCM2P8COPnYDwAwujXUvwMGgDJUaZQPAGPDYDW00LXXDAAAlCEBAAAEAABAAAAABAAAQAAoCceOHYt169ZFfX19ZDKZmDNnjr0CoAwV8x/Xjcm/dyRvBBSR/2WCPesv1GavX78+7rvvvj7bWOj3ASC/elJdXR1nnXVWXHrppfGTn/wkLr744oLWh1x+vxg1otj1UwA4zcKFC+Ott96KrVu3xk033RSZTKZojQtAYepJVVVVPPPMM3H11VcLAALA8NTU1MSJEyeis7PzlG0XAADGRgDo6Yc7Ozvjn//8Z/zsZz+LHTt2xBe+8IX461//WrT3K/UAULLnAPzud7+Lr371q/HZz342qqurY+7cufGDH/wgWltbT/mwOzs7o7u7OyZMmND74Z8eBE5+ADA6MplMXHDBBfHII49ERMS+ffv6FNDT++n29vZYu3Zt1NfXR1VVVcydOzceeOCBmDRp0oB9+rvvvhu33nprTJ06NWbMmBF33XVXdHR09Fuox3ONKMkZgO985zuxZcuWfl+bP39+/OUvf4kpU6b0u60nH/8fiQQGQG79/ZtvvhmLFi2K+vr6+Ne//jXg8t3d3bF06dJ4+eWXs+rTe37/zDPPPGWwGBGxbt26ePDBB4esc/nUCDMAefrNb34TW7ZsiVmzZsWOHTviwIED0dbWFs3NzXHFFVfEvn374uc//3mfD/P//2vkAZ8/+XUARt7hw4fjpZdeiptvvjkiIm655ZZBl3/88cfj5ZdfjunTp8fTTz8dhw8fjoMHD8bOnTsH/b0LL7wwdu3aFYcOHYo1a9ZERMS2bdv6LcTjuUaU3AzAZZddFq+88ko0NzfHRRdddMpr7733XsyePTsWLVoUe/fuHXR9zgEAGBszAP257rrrYtu2bb0nbvfXb3/xi1+M5ubm2L59e9x4441D9vE9zx0/fjwmTPi/8fGBAwfi7LPPjkwm0+9hACcBjqEAMGnSpDh69Oig66ipqYn29nYBAGAcBoD169f3jswH67d76sHBgwfjrLPOyjoAnPzcsWPHoqqqKqtlx1sAmDCcDRzscfp0yEhPj5w4cWLIZU5OcQCMbT3149FHH42IiM2bN8f+/fuH/L2urq6IiKitrR32e1dWVo743znQY6j6W/QAMNYtXLgwIiLeeeedggSRzs5O3z6AMWDVqlVxzz33xAcffBBXXXVVfPTRR4MuP3PmzIiI2L17d9G2aTzXiJILAHfccUdERFxxxRWxdevWePfdd6OjoyPa29tj79698dhjj/W5e9RgO85DDz0UbW1tvnkAY8CGDRvi2muvjTfffDOuueaaQQvwlVdeGRERd999d+zZsyeOHj0azc3Ncdttt+W9HaVQI3I+B2Ckj1Hk+v7Hjx+P22+/PX79619ntZ0DHcf57ne/G7/61a9G/O8DIAbtn9va2uLyyy+P5ubmuOGGG2LHjh2nTIP3LP/2229HY2NjHDly5JTfr66u7j08kM1x/f6eH40aUej6W3IzABMmTIitW7fGH/7wh/ja174Ws2bNiurq6shkMrFw4cL43ve+N+g1oSenzHvvvTfOO++8yGQyMWXKlLjkkkt8IwFG2cSJE+PZZ5+NOXPmxFNPPRU//OEP+11u3rx58eKLL8aSJUuipqYmJk+eHCtWrIhXXnklIv7vhPB8ZiLGe40YdzMAAJCPPXv2xIUXXhjz5s3rczfB8TAjUqj6W2lXAKAcdHd3x969e2PVqlUREbF8+fKy/jzMAABQukVugJo1Y8aMeOONN3pP5ivHGYCczwHI9zpF/1AHgJGyYsWKmD17dtTW1vb+Y7g777wzXn/99TFV/LOpnYW+z86I3wnQLAEAjH7tnOBjB4DyIwAAgAAAAAgAAIAAAAAIAACAAAAAjBc53QrYNf4AUHjZ1M5C12AzAABQhgQAABAAAAABAAAQAAAAAQAAEAAAAAEAABizcroRUKFuVJDtugCg1I1W3awc7x+KIAGAGlViAWAkGkiAAFDAy7E+VNoFhrdzCA4A+moBgCF3RDshgH5UAGDAndwODujzEADo84XxZQH0VwgAvmy+aIC+h2FxI6AS/GJme00pgH5FAKDEUzqAPoSTVRZ6R8h2OqhQN1DI9zrO4V4+kutZqtme/DLUMbSBpt56nu95rqKiIlJKvT8Bci3+p/chp/czg/VJ2fRnufSNw+l38+njC1FfClnrilGHzQCUqJ4dQPEH9CHkNQPA+PiyAuhnEAB8AQH0SQgAvkwA+jMEAF8EAH2jAICdFkC/KwDYoQDQxwsAGhcA4UEA8MECwLiudRVJJQaAsuNOgAAgAAAAAgAAIAAAAAIAACAAAAACAAAgAAAAAgAAMIr+HyP6AtxN3EzKAAAAAElFTkSuQmCC" + } + ], + "materials" : [ + { + "name" : "BackPlaneMat", + "doubleSided": true, + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 0.16000001668930075, + 0.16000001668930075, + 0.16000001668930075, + 1.0 + ], + "metallicFactor" : 0.0 + } + }, + { + "name" : "BottomLeftMat", + "doubleSided": true, + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 0.0, + 0.16000000476837162, + 0.800000011920929, + 1.0 + ], + "baseColorTexture" : { + "index" : 0 + }, + "metallicFactor" : 0.0 + } + }, + { + "name" : "BottomRightMat", + "doubleSided": true, + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 0.0, + 0.800000011920929, + 0.0, + 1.0 + ], + "baseColorTexture" : { + "index" : 0 + }, + "metallicFactor" : 0.0 + } + }, + { + "name" : "TopLeftMat", + "doubleSided": true, + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 0.800000011920929, + 0.800000011920929, + 0.0, + 1.0 + ], + "baseColorTexture" : { + "index" : 0 + }, + "metallicFactor" : 0.0 + } + }, + { + "name" : "TopRightMat", + "doubleSided": true, + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 0.800000011920929, + 0.08000000238418581, + 0.0, + 1.0 + ], + "baseColorTexture" : { + "index" : 0 + }, + "metallicFactor" : 0.0 + } + } + ], + "meshes" : [ + { + "name" : "TopRightMesh", + "primitives" : [ + { + "attributes" : { + "NORMAL" : 2, + "POSITION" : 1, + "TEXCOORD_1" : 3 + }, + "indices" : 0, + "material" : 4 + } + ] + }, + { + "name" : "TopLeftMesh", + "primitives" : [ + { + "attributes" : { + "NORMAL" : 6, + "POSITION" : 5, + "TEXCOORD_0" : 7 + }, + "indices" : 4, + "material" : 3 + } + ] + }, + { + "name" : "BottomRightMesh", + "primitives" : [ + { + "attributes" : { + "NORMAL" : 10, + "POSITION" : 9, + "TEXCOORD_0" : 11 + }, + "indices" : 8, + "material" : 2 + } + ] + }, + { + "name" : "BackPlaneMesh", + "primitives" : [ + { + "attributes" : { + "NORMAL" : 14, + "POSITION" : 13 + }, + "indices" : 12, + "material" : 0 + } + ] + }, + { + "name" : "BottomLeftMesh", + "primitives" : [ + { + "attributes" : { + "NORMAL" : 17, + "POSITION" : 16, + "TEXCOORD_0" : 18 + }, + "indices" : 15, + "material" : 1 + } + ] + } + ], + "nodes" : [ + { + "mesh" : 3, + "name" : "BackPlane" + }, + { + "mesh" : 4, + "name" : "BottomLeftObj" + }, + { + "mesh" : 2, + "name" : "BottomRightObj" + }, + { + "mesh" : 1, + "name" : "TopLeftObj" + }, + { + "mesh" : 0, + "name" : "TopRightObj" + } + ], + "samplers" : [ + {} + ], + "scene" : 0, + "scenes" : [ + { + "name" : "Scene", + "nodes" : [ + 0, + 2, + 1, + 4, + 3 + ] + } + ], + "textures" : [ + { + "sampler" : 0, + "source" : 0 + } + ] +} diff --git a/test/unit/utglTF2ImportExport.cpp b/test/unit/utglTF2ImportExport.cpp index f0f18d503..8fa5e08ce 100644 --- a/test/unit/utglTF2ImportExport.cpp +++ b/test/unit/utglTF2ImportExport.cpp @@ -534,3 +534,9 @@ TEST_F(utglTF2ImportExport, norootnode_scenewithoutnodes) { ASSERT_NE(scene, nullptr); ASSERT_NE(scene->mRootNode, nullptr); } + +TEST_F(utglTF2ImportExport, norootnode_issue_3269) { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/issue_3269/texcoord_crash.gltf", aiProcess_ValidateDataStructure); + ASSERT_NE(scene, nullptr); +} From ad62e6e863d7b144d0c6118701be42add4874cf6 Mon Sep 17 00:00:00 2001 From: kimkulling Date: Fri, 12 Jun 2020 12:29:51 +0200 Subject: [PATCH 30/62] fix unittest check - cannot work, just crash shall not occurr any more. --- code/AssetLib/glTF2/glTF2Asset.inl | 2 +- test/unit/utglTF2ImportExport.cpp | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/code/AssetLib/glTF2/glTF2Asset.inl b/code/AssetLib/glTF2/glTF2Asset.inl index 80207a4be..5a99525b2 100644 --- a/code/AssetLib/glTF2/glTF2Asset.inl +++ b/code/AssetLib/glTF2/glTF2Asset.inl @@ -722,7 +722,7 @@ template void Accessor::ExtractData(T *&outData) { uint8_t *data = GetPointer(); if (!data) { - throw DeadlyImportError("GLTF: data is NULL"); + throw DeadlyImportError("GLTF2: data is nullptr."); } const size_t elemSize = GetElementSize(); diff --git a/test/unit/utglTF2ImportExport.cpp b/test/unit/utglTF2ImportExport.cpp index 8fa5e08ce..6791d5f89 100644 --- a/test/unit/utglTF2ImportExport.cpp +++ b/test/unit/utglTF2ImportExport.cpp @@ -535,8 +535,9 @@ TEST_F(utglTF2ImportExport, norootnode_scenewithoutnodes) { ASSERT_NE(scene->mRootNode, nullptr); } +// Shall not crash! TEST_F(utglTF2ImportExport, norootnode_issue_3269) { Assimp::Importer importer; const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/issue_3269/texcoord_crash.gltf", aiProcess_ValidateDataStructure); - ASSERT_NE(scene, nullptr); + ASSERT_EQ(scene, nullptr); } From f938a6b744bf9a951f60016dd982520fc3a41d4f Mon Sep 17 00:00:00 2001 From: kimkulling Date: Fri, 12 Jun 2020 14:52:02 +0200 Subject: [PATCH 31/62] fix leak: just ignore broken texture coordinates. --- code/AssetLib/glTF2/glTF2Importer.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/AssetLib/glTF2/glTF2Importer.cpp b/code/AssetLib/glTF2/glTF2Importer.cpp index a957d9d9b..1c044e7ce 100644 --- a/code/AssetLib/glTF2/glTF2Importer.cpp +++ b/code/AssetLib/glTF2/glTF2Importer.cpp @@ -417,7 +417,8 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { } for (size_t tc = 0; tc < attr.texcoord.size() && tc < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++tc) { if (!attr.texcoord[tc]) { - throw DeadlyImportError("GLTF: Texture coordinate accessor not found or non-contiguous texture coordinate sets"); + DefaultLogger::get()->warn("Texture coordinate accessor not found or non-contiguous texture coordinate sets."); + continue; } if (attr.texcoord[tc]->count != aim->mNumVertices) { From f0f6612b81c1eec1ba2ebc8bcdfb227252223174 Mon Sep 17 00:00:00 2001 From: kimkulling Date: Mon, 15 Jun 2020 20:52:11 +0200 Subject: [PATCH 32/62] disable warning for radjson. --- contrib/rapidjson/include/rapidjson/document.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/contrib/rapidjson/include/rapidjson/document.h b/contrib/rapidjson/include/rapidjson/document.h index 93b091f64..473d846e3 100644 --- a/contrib/rapidjson/include/rapidjson/document.h +++ b/contrib/rapidjson/include/rapidjson/document.h @@ -17,6 +17,11 @@ /*! \file document.h */ +#if (__GNUC__ >= 8 && __GNUC_MINOR__ >= 0) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wclass-memaccess" +#endif + #include "reader.h" #include "internal/meta.h" #include "internal/strfunc.h" @@ -2610,4 +2615,8 @@ private: RAPIDJSON_NAMESPACE_END RAPIDJSON_DIAG_POP +#if (__GNUC__ == 8 && __GNUC_MINOR__ >= 0) +#pragma GCC diagnostic pop +#endif + #endif // RAPIDJSON_DOCUMENT_H_ From 524e2e4728a6b62d6fc6e33239031b30f7fc7a6c Mon Sep 17 00:00:00 2001 From: kimkulling Date: Mon, 15 Jun 2020 21:34:49 +0200 Subject: [PATCH 33/62] fix warning, hopefully ... --- code/Common/SceneCombiner.cpp | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/code/Common/SceneCombiner.cpp b/code/Common/SceneCombiner.cpp index 4f262192b..5d49baaf4 100644 --- a/code/Common/SceneCombiner.cpp +++ b/code/Common/SceneCombiner.cpp @@ -66,6 +66,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace Assimp { +#if (__GNUC__ >= 8 && __GNUC_MINOR__ >= 0) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wclass-memaccess" +#endif + // ------------------------------------------------------------------------------------------------ // Add a prefix to a string inline @@ -75,7 +80,7 @@ void PrefixString(aiString& string,const char* prefix, unsigned int len) { return; if (len+string.length>=MAXLEN-1) { - ASSIMP_LOG_VERBOSE_DEBUG("Can't add an unique prefix because the string is too long"); + ASSIMP_LOG_VERBOSE_DEBUG("Can't add an unique prefix because the string is too long"); ai_assert(false); return; } @@ -98,8 +103,9 @@ void SceneCombiner::AddNodeHashes(aiNode* node, std::set& hashes) } // Process all children recursively - for (unsigned int i = 0; i < node->mNumChildren;++i) + for (unsigned int i = 0; i < node->mNumChildren;++i) { AddNodeHashes(node->mChildren[i],hashes); + } } // ------------------------------------------------------------------------------------------------ @@ -978,9 +984,7 @@ void GetArrayCopy(Type*& dest, ai_uint num ) { Type* old = dest; dest = new Type[num]; - for ( size_t i=0; imBitangents, dest->mNumVertices ); unsigned int n = 0; - while (dest->HasTextureCoords(n)) - GetArrayCopy( dest->mTextureCoords[n++], dest->mNumVertices ); + while (dest->HasTextureCoords(n)) { + GetArrayCopy( dest->mTextureCoords[n++], dest->mNumVertices ); + } n = 0; - while (dest->HasVertexColors(n)) - GetArrayCopy( dest->mColors[n++], dest->mNumVertices ); + while (dest->HasVertexColors(n)) { + GetArrayCopy( dest->mColors[n++], dest->mNumVertices ); + } // make a deep copy of all bones CopyPtrArray(dest->mBones,dest->mBones,dest->mNumBones); @@ -1343,5 +1349,9 @@ void SceneCombiner::Copy(aiMetadata** _dest, const aiMetadata* src) { } } +#if (__GNUC__ >= 8 && __GNUC_MINOR__ >= 0) +# pragma GCC diagnostic pop +#endif + } // Namespace Assimp From bb613df5431dfa4cbc0ccc5396d768e08a8ae076 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 16 Jun 2020 16:31:47 +0200 Subject: [PATCH 34/62] Update issue templates To make our life easier --- .github/ISSUE_TEMPLATE/bug_report.md | 38 +++++++++++++++++++++++ .github/ISSUE_TEMPLATE/feature_request.md | 20 ++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 000000000..dd84ea782 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,38 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Desktop (please complete the following information):** + - OS: [e.g. iOS] + - Browser [e.g. chrome, safari] + - Version [e.g. 22] + +**Smartphone (please complete the following information):** + - Device: [e.g. iPhone6] + - OS: [e.g. iOS8.1] + - Browser [e.g. stock browser, safari] + - Version [e.g. 22] + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 000000000..bbcbbe7d6 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: '' +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. From b3af5c5a14e4e54abf531c76a0f103eb57b1688d Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 17 Jun 2020 20:37:39 +0200 Subject: [PATCH 35/62] closes https://github.com/assimp/assimp/issues/3253 : remove useless code --- code/AssetLib/Obj/ObjFileParser.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/code/AssetLib/Obj/ObjFileParser.cpp b/code/AssetLib/Obj/ObjFileParser.cpp index a825b96ca..ecf51240b 100644 --- a/code/AssetLib/Obj/ObjFileParser.cpp +++ b/code/AssetLib/Obj/ObjFileParser.cpp @@ -253,7 +253,6 @@ static bool isDataDefinitionEnd(const char *tmp) { if (*tmp == '\\') { tmp++; if (IsLineEnd(*tmp)) { - tmp++; return true; } } From 6acaaee80f51fa43e62f55a8728bdfb26d364be2 Mon Sep 17 00:00:00 2001 From: Kota Iguchi Date: Sat, 20 Jun 2020 15:27:28 +0900 Subject: [PATCH 36/62] Check invalid vertex id for bone weight --- code/PostProcessing/LimitBoneWeightsProcess.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/code/PostProcessing/LimitBoneWeightsProcess.cpp b/code/PostProcessing/LimitBoneWeightsProcess.cpp index 5b8934159..b4f0b48d8 100644 --- a/code/PostProcessing/LimitBoneWeightsProcess.cpp +++ b/code/PostProcessing/LimitBoneWeightsProcess.cpp @@ -114,6 +114,10 @@ void LimitBoneWeightsProcess::ProcessMesh(aiMesh* pMesh) for (unsigned int w = 0; w < bone->mNumWeights; ++w) { const aiVertexWeight& vw = bone->mWeights[w]; + + if (vertexWeights.size() <= vw.mVertexId) + continue; + vertexWeights[vw.mVertexId].push_back(Weight(b, vw.mWeight)); maxVertexWeights = std::max(maxVertexWeights, vertexWeights[vw.mVertexId].size()); } From 6397bfbf904415d75b55c7389cb66a9958359a04 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 21 Jun 2020 12:03:38 +0200 Subject: [PATCH 37/62] replace NULL by nullptr on loadFile. --- code/AMF/AMFImporter.cpp | 4 +++- code/BVH/BVHLoader.cpp | 10 ++++++---- code/CSM/CSMLoader.cpp | 2 +- code/HMP/HMPLoader.cpp | 5 +++-- code/Irr/IRRMeshLoader.cpp | 5 +++-- code/LWS/LWSLoader.cpp | 2 +- code/MD2/MD2Loader.cpp | 11 ++++++----- code/MD3/MD3Loader.cpp | 5 +++-- code/MD5/MD5Loader.cpp | 11 +++++------ code/MDL/HalfLife/HL1MDLLoader.h | 6 ++++-- code/Raw/RawLoader.cpp | 2 +- code/X/XFileImporter.cpp | 2 +- include/assimp/irrXMLWrapper.h | 2 +- 13 files changed, 38 insertions(+), 29 deletions(-) diff --git a/code/AMF/AMFImporter.cpp b/code/AMF/AMFImporter.cpp index df4324d4d..d93ca54cf 100644 --- a/code/AMF/AMFImporter.cpp +++ b/code/AMF/AMFImporter.cpp @@ -407,7 +407,9 @@ void AMFImporter::ParseFile(const std::string& pFile, IOSystem* pIOHandler) std::unique_ptr file(pIOHandler->Open(pFile, "rb")); // Check whether we can read from the file - if(file.get() == NULL) throw DeadlyImportError("Failed to open AMF file " + pFile + "."); + if (file.get() == nullptr) { + throw DeadlyImportError("Failed to open AMF file " + pFile + "."); + } // generate a XML reader for it std::unique_ptr mIOWrapper(new CIrrXML_IOStreamReader(file.get())); diff --git a/code/BVH/BVHLoader.cpp b/code/BVH/BVHLoader.cpp index 1110754c2..5d335d233 100644 --- a/code/BVH/BVHLoader.cpp +++ b/code/BVH/BVHLoader.cpp @@ -124,12 +124,14 @@ void BVHLoader::InternReadFile( const std::string& pFile, aiScene* pScene, IOSys // read file into memory std::unique_ptr file( pIOHandler->Open( pFile)); - if( file.get() == NULL) - throw DeadlyImportError( "Failed to open file " + pFile + "."); + if (file.get() == nullptr) { + throw DeadlyImportError("Failed to open file " + pFile + "."); + } size_t fileSize = file->FileSize(); - if( fileSize == 0) - throw DeadlyImportError( "File is too small."); + if (fileSize == 0) { + throw DeadlyImportError("File is too small."); + } mBuffer.resize( fileSize); file->Read( &mBuffer.front(), 1, fileSize); diff --git a/code/CSM/CSMLoader.cpp b/code/CSM/CSMLoader.cpp index fbabea12e..47563feb1 100644 --- a/code/CSM/CSMLoader.cpp +++ b/code/CSM/CSMLoader.cpp @@ -127,7 +127,7 @@ void CSMImporter::InternReadFile( const std::string& pFile, std::unique_ptr file( pIOHandler->Open( pFile, "rb")); // Check whether we can read from the file - if( file.get() == NULL) { + if( file.get() == nullptr) { throw DeadlyImportError( "Failed to open CSM file " + pFile + "."); } diff --git a/code/HMP/HMPLoader.cpp b/code/HMP/HMPLoader.cpp index 0dea09ee0..45f45d022 100644 --- a/code/HMP/HMPLoader.cpp +++ b/code/HMP/HMPLoader.cpp @@ -122,8 +122,9 @@ void HMPImporter::InternReadFile( const std::string& pFile, std::unique_ptr file(mIOHandler->Open(pFile)); // Check whether we can read from the file - if( file.get() == nullptr) - throw DeadlyImportError( "Failed to open HMP file " + pFile + "."); + if (file.get() == nullptr) { + throw DeadlyImportError("Failed to open HMP file " + pFile + "."); + } // Check whether the HMP file is large enough to contain // at least the file header diff --git a/code/Irr/IRRMeshLoader.cpp b/code/Irr/IRRMeshLoader.cpp index 13db70e91..d07ff87ea 100644 --- a/code/Irr/IRRMeshLoader.cpp +++ b/code/Irr/IRRMeshLoader.cpp @@ -139,8 +139,9 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile, std::unique_ptr file( pIOHandler->Open( pFile)); // Check whether we can read from the file - if( file.get() == NULL) - throw DeadlyImportError( "Failed to open IRRMESH file " + pFile + ""); + if (file.get() == nullptr) { + throw DeadlyImportError("Failed to open IRRMESH file " + pFile + "."); + } // Construct the irrXML parser CIrrXML_IOStreamReader st(file.get()); diff --git a/code/LWS/LWSLoader.cpp b/code/LWS/LWSLoader.cpp index 952c3ccbc..d02d24ea3 100644 --- a/code/LWS/LWSLoader.cpp +++ b/code/LWS/LWSLoader.cpp @@ -501,7 +501,7 @@ void LWSImporter::InternReadFile(const std::string &pFile, aiScene *pScene, std::unique_ptr file(pIOHandler->Open(pFile, "rb")); // Check whether we can read from the file - if (file.get() == NULL) { + if (file.get() == nullptr) { throw DeadlyImportError("Failed to open LWS file " + pFile + "."); } diff --git a/code/MD2/MD2Loader.cpp b/code/MD2/MD2Loader.cpp index 473ab99bc..abc5f06ff 100644 --- a/code/MD2/MD2Loader.cpp +++ b/code/MD2/MD2Loader.cpp @@ -221,20 +221,21 @@ void MD2Importer::InternReadFile( const std::string& pFile, std::unique_ptr file( pIOHandler->Open( pFile)); // Check whether we can read from the file - if( file.get() == NULL) - throw DeadlyImportError( "Failed to open MD2 file " + pFile + ""); + if (file.get() == nullptr) { + throw DeadlyImportError("Failed to open MD2 file " + pFile + ""); + } // check whether the md3 file is large enough to contain // at least the file header fileSize = (unsigned int)file->FileSize(); - if( fileSize < sizeof(MD2::Header)) - throw DeadlyImportError( "MD2 File is too small"); + if (fileSize < sizeof(MD2::Header)) { + throw DeadlyImportError("MD2 File is too small"); + } std::vector mBuffer2(fileSize); file->Read(&mBuffer2[0], 1, fileSize); mBuffer = &mBuffer2[0]; - m_pcHeader = (BE_NCONST MD2::Header*)mBuffer; #ifdef AI_BUILD_BIG_ENDIAN diff --git a/code/MD3/MD3Loader.cpp b/code/MD3/MD3Loader.cpp index 2051ecdda..28799c0fc 100644 --- a/code/MD3/MD3Loader.cpp +++ b/code/MD3/MD3Loader.cpp @@ -747,8 +747,9 @@ void MD3Importer::InternReadFile( const std::string& pFile, aiScene* pScene, IOS std::unique_ptr file( pIOHandler->Open( pFile)); // Check whether we can read from the file - if( file.get() == NULL) - throw DeadlyImportError( "Failed to open MD3 file " + pFile + "."); + if (file.get() == nullptr) { + throw DeadlyImportError("Failed to open MD3 file " + pFile + "."); + } // Check whether the md3 file is large enough to contain the header fileSize = (unsigned int)file->FileSize(); diff --git a/code/MD5/MD5Loader.cpp b/code/MD5/MD5Loader.cpp index d428873df..2aa07df18 100644 --- a/code/MD5/MD5Loader.cpp +++ b/code/MD5/MD5Loader.cpp @@ -332,13 +332,12 @@ void MD5Importer::AttachChilds_Anim(int iParentID, aiNode *piParent, AnimBoneLis // ------------------------------------------------------------------------------------------------ // Load a MD5MESH file void MD5Importer::LoadMD5MeshFile() { - std::string pFile = mFile + "md5mesh"; - std::unique_ptr file(mIOHandler->Open(pFile, "rb")); + std::string filename = mFile + "md5mesh"; + std::unique_ptr file(mIOHandler->Open(filename, "rb")); // Check whether we can read from the file if (file.get() == nullptr || !file->FileSize()) { - ASSIMP_LOG_WARN("Failed to access MD5MESH file: " + pFile); - return; + throw DeadlyImportError("Failed to open MD5 file " + filename + "."); } bHadMD5Mesh = true; LoadFileIntoMemory(file.get()); @@ -552,9 +551,9 @@ void MD5Importer::LoadMD5AnimFile() { // Check whether we can read from the file if (!file.get() || !file->FileSize()) { - ASSIMP_LOG_WARN("Failed to read MD5ANIM file: " + pFile); - return; + throw DeadlyImportError("Failed to open MD3 file " + file + "."); } + LoadFileIntoMemory(file.get()); // parse the basic file structure diff --git a/code/MDL/HalfLife/HL1MDLLoader.h b/code/MDL/HalfLife/HL1MDLLoader.h index c4293259c..2891ddb1e 100644 --- a/code/MDL/HalfLife/HL1MDLLoader.h +++ b/code/MDL/HalfLife/HL1MDLLoader.h @@ -222,12 +222,14 @@ void HL1MDLLoader::load_file_into_buffer(const std::string &file_path, unsigned std::unique_ptr file(io_->Open(file_path)); - if (file.get() == NULL) + if (file.get() == nullptr) { throw DeadlyImportError("Failed to open MDL file " + DefaultIOSystem::fileName(file_path) + "."); + } const size_t file_size = file->FileSize(); - if (file_size < sizeof(MDLFileHeader)) + if (file_size < sizeof(MDLFileHeader)) { throw DeadlyImportError("MDL file is too small."); + } buffer = new unsigned char[1 + file_size]; file->Read((void *)buffer, 1, file_size); diff --git a/code/Raw/RawLoader.cpp b/code/Raw/RawLoader.cpp index 092323cc0..bb58026f0 100644 --- a/code/Raw/RawLoader.cpp +++ b/code/Raw/RawLoader.cpp @@ -104,7 +104,7 @@ void RAWImporter::InternReadFile( const std::string& pFile, std::unique_ptr file( pIOHandler->Open( pFile, "rb")); // Check whether we can read from the file - if( file.get() == NULL) { + if( file.get() == nullptr) { throw DeadlyImportError( "Failed to open RAW file " + pFile + "."); } diff --git a/code/X/XFileImporter.cpp b/code/X/XFileImporter.cpp index 846023b93..0b256b0bc 100644 --- a/code/X/XFileImporter.cpp +++ b/code/X/XFileImporter.cpp @@ -113,7 +113,7 @@ const aiImporterDesc* XFileImporter::GetInfo () const { void XFileImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) { // read file into memory std::unique_ptr file( pIOHandler->Open( pFile)); - if ( file.get() == NULL ) { + if ( file.get() == nullptr ) { throw DeadlyImportError( "Failed to open file " + pFile + "." ); } diff --git a/include/assimp/irrXMLWrapper.h b/include/assimp/irrXMLWrapper.h index 65a7be298..52c174791 100644 --- a/include/assimp/irrXMLWrapper.h +++ b/include/assimp/irrXMLWrapper.h @@ -63,7 +63,7 @@ namespace Assimp { * @code * // open the file * std::unique_ptr file( pIOHandler->Open( pFile)); - * if( file.get() == NULL) { + * if( file.get() == nullptr ) { * throw DeadlyImportError( "Failed to open file " + pFile + "."); * } * From ba09e1ef94176a97766203f36a850c6fe9c58c8c Mon Sep 17 00:00:00 2001 From: Filip Lundgren <45687559+ifiddynine@users.noreply.github.com> Date: Sun, 21 Jun 2020 23:56:11 +0200 Subject: [PATCH 38/62] Fix Blender .fbx metalness detection --- code/AssetLib/FBX/FBXConverter.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/code/AssetLib/FBX/FBXConverter.cpp b/code/AssetLib/FBX/FBXConverter.cpp index 261567e48..09711ee8d 100644 --- a/code/AssetLib/FBX/FBXConverter.cpp +++ b/code/AssetLib/FBX/FBXConverter.cpp @@ -1992,6 +1992,7 @@ void FBXConverter::SetTextureProperties(aiMaterial *out_mat, const TextureMap &_ TrySetTextureProperties(out_mat, _textures, "ShininessExponent", aiTextureType_SHININESS, mesh); TrySetTextureProperties(out_mat, _textures, "TransparencyFactor", aiTextureType_OPACITY, mesh); TrySetTextureProperties(out_mat, _textures, "EmissiveFactor", aiTextureType_EMISSIVE, mesh); + TrySetTextureProperties(out_mat, _textures, "ReflectionFactor", aiTextureType_METALNESS, mesh); //Maya counterparts TrySetTextureProperties(out_mat, _textures, "Maya|DiffuseTexture", aiTextureType_DIFFUSE, mesh); TrySetTextureProperties(out_mat, _textures, "Maya|NormalTexture", aiTextureType_NORMALS, mesh); From 20062865286d221b79e42b4eb3182d5ee7f91bd7 Mon Sep 17 00:00:00 2001 From: Filip Lundgren <45687559+ifiddynine@users.noreply.github.com> Date: Mon, 22 Jun 2020 23:14:16 +0200 Subject: [PATCH 39/62] Fix Maya PBR & stingray texture detection --- code/AssetLib/FBX/FBXConverter.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/code/AssetLib/FBX/FBXConverter.cpp b/code/AssetLib/FBX/FBXConverter.cpp index 261567e48..0a13ff766 100644 --- a/code/AssetLib/FBX/FBXConverter.cpp +++ b/code/AssetLib/FBX/FBXConverter.cpp @@ -2000,19 +2000,19 @@ void FBXConverter::SetTextureProperties(aiMaterial *out_mat, const TextureMap &_ TrySetTextureProperties(out_mat, _textures, "Maya|ReflectionMapTexture", aiTextureType_REFLECTION, mesh); // Maya PBR - TrySetTextureProperties(out_mat, _textures, "Maya|baseColor|file", aiTextureType_BASE_COLOR, mesh); - TrySetTextureProperties(out_mat, _textures, "Maya|normalCamera|file", aiTextureType_NORMAL_CAMERA, mesh); - TrySetTextureProperties(out_mat, _textures, "Maya|emissionColor|file", aiTextureType_EMISSION_COLOR, mesh); - TrySetTextureProperties(out_mat, _textures, "Maya|metalness|file", aiTextureType_METALNESS, mesh); - TrySetTextureProperties(out_mat, _textures, "Maya|diffuseRoughness|file", aiTextureType_DIFFUSE_ROUGHNESS, mesh); + TrySetTextureProperties(out_mat, _textures, "Maya|baseColor", aiTextureType_BASE_COLOR, mesh); + TrySetTextureProperties(out_mat, _textures, "Maya|normalCamera", aiTextureType_NORMAL_CAMERA, mesh); + TrySetTextureProperties(out_mat, _textures, "Maya|emissionColor", aiTextureType_EMISSION_COLOR, mesh); + TrySetTextureProperties(out_mat, _textures, "Maya|metalness", aiTextureType_METALNESS, mesh); + TrySetTextureProperties(out_mat, _textures, "Maya|diffuseRoughness", aiTextureType_DIFFUSE_ROUGHNESS, mesh); // Maya stingray - TrySetTextureProperties(out_mat, _textures, "Maya|TEX_color_map|file", aiTextureType_BASE_COLOR, mesh); - TrySetTextureProperties(out_mat, _textures, "Maya|TEX_normal_map|file", aiTextureType_NORMAL_CAMERA, mesh); - TrySetTextureProperties(out_mat, _textures, "Maya|TEX_emissive_map|file", aiTextureType_EMISSION_COLOR, mesh); - TrySetTextureProperties(out_mat, _textures, "Maya|TEX_metallic_map|file", aiTextureType_METALNESS, mesh); - TrySetTextureProperties(out_mat, _textures, "Maya|TEX_roughness_map|file", aiTextureType_DIFFUSE_ROUGHNESS, mesh); - TrySetTextureProperties(out_mat, _textures, "Maya|TEX_ao_map|file", aiTextureType_AMBIENT_OCCLUSION, mesh); + TrySetTextureProperties(out_mat, _textures, "Maya|TEX_color_map", aiTextureType_BASE_COLOR, mesh); + TrySetTextureProperties(out_mat, _textures, "Maya|TEX_normal_map", aiTextureType_NORMAL_CAMERA, mesh); + TrySetTextureProperties(out_mat, _textures, "Maya|TEX_emissive_map", aiTextureType_EMISSION_COLOR, mesh); + TrySetTextureProperties(out_mat, _textures, "Maya|TEX_metallic_map", aiTextureType_METALNESS, mesh); + TrySetTextureProperties(out_mat, _textures, "Maya|TEX_roughness_map", aiTextureType_DIFFUSE_ROUGHNESS, mesh); + TrySetTextureProperties(out_mat, _textures, "Maya|TEX_ao_map", aiTextureType_AMBIENT_OCCLUSION, mesh); // 3DSMax PBR TrySetTextureProperties(out_mat, _textures, "3dsMax|Parameters|base_color_map", aiTextureType_BASE_COLOR, mesh); From 5717ea466f04584b157598b568c98615bea6f71f Mon Sep 17 00:00:00 2001 From: Ryan Styrczula Date: Mon, 22 Jun 2020 17:19:26 -0400 Subject: [PATCH 40/62] FindInvalidDataProcess: Mark removed meshes as "out" There's a code path where an input scene only has a single mesh. In this case, if ProcessMesh returns 2, we delete the mesh and move on with the postprocessing. UpdateMeshReferences is not called and so the deleted mesh is left dangling in nodes. In a later step (SplitMesh in my testing), it then tries to deference a null pointer and we explode. With `out = true`, we can now hit the DeadlyImportError instead of a segfault. --- code/PostProcessing/FindInvalidDataProcess.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/code/PostProcessing/FindInvalidDataProcess.cpp b/code/PostProcessing/FindInvalidDataProcess.cpp index 3ad2446b3..42c5a4ca9 100644 --- a/code/PostProcessing/FindInvalidDataProcess.cpp +++ b/code/PostProcessing/FindInvalidDataProcess.cpp @@ -127,6 +127,7 @@ void FindInvalidDataProcess::Execute(aiScene *pScene) { pScene->mMeshes[a] = NULL; meshMapping[a] = UINT_MAX; + out = true; continue; } From 9188f56839a29f2ef526e47c492681d0338cec72 Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Tue, 23 Jun 2020 11:55:51 +0100 Subject: [PATCH 41/62] Allow assert handling to be replaced. --- code/CMakeLists.txt | 1 + code/Common/AssertHandler.cpp | 72 +++++++++++++++++ code/Common/AssertHandler.h | 75 ++++++++++++++++++ include/assimp/ai_assert.h | 16 ++-- test/CMakeLists.txt | 1 + test/unit/Common/utAssertHandler.cpp | 111 +++++++++++++++++++++++++++ 6 files changed, 269 insertions(+), 7 deletions(-) create mode 100644 code/Common/AssertHandler.cpp create mode 100644 code/Common/AssertHandler.h create mode 100644 test/unit/Common/utAssertHandler.cpp diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 000ebad6c..9f8f519d9 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -199,6 +199,7 @@ SET( Common_SRCS Common/simd.h Common/simd.cpp Common/material.cpp + Common/AssertHandler.cpp ) SOURCE_GROUP(Common FILES ${Common_SRCS}) diff --git a/code/Common/AssertHandler.cpp b/code/Common/AssertHandler.cpp new file mode 100644 index 000000000..63b64f828 --- /dev/null +++ b/code/Common/AssertHandler.cpp @@ -0,0 +1,72 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2020, assimp team + + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +/** @file AssertHandler.cpp + * @brief Implementation of assert handling logic. + */ + +#include "AssertHandler.h" + +#include +#include + +void Assimp::defaultAiAssertHandler(const char* failedExpression, const char* file, int line) +{ + std::cerr << "ai_assert failure in " << file << "(" << line << "): " << failedExpression << std::endl; + std::abort(); +} + +namespace +{ + Assimp::AiAssertHandler s_handler = Assimp::defaultAiAssertHandler; +} + +void Assimp::setAiAssertHandler(AiAssertHandler handler) +{ + s_handler = handler; +} + +void Assimp::aiAssertViolation(const char* failedExpression, const char* file, int line) +{ + s_handler(failedExpression, file, line); +} diff --git a/code/Common/AssertHandler.h b/code/Common/AssertHandler.h new file mode 100644 index 000000000..2515f0bf2 --- /dev/null +++ b/code/Common/AssertHandler.h @@ -0,0 +1,75 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2020, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + +/** @file Provides facilities to replace the default assert handler. */ + +#ifndef INCLUDED_AI_ASSERTHANDLER_H +#define INCLUDED_AI_ASSERTHANDLER_H + +#include +#include + +namespace Assimp +{ + // --------------------------------------------------------------------------- + /** Signature of functions which handle assert violations. + */ + using AiAssertHandler = void (*)(const char* failedExpression, const char* file, int line); + + // --------------------------------------------------------------------------- + /** Set the assert handler. + */ + ASSIMP_API void setAiAssertHandler(AiAssertHandler handler); + + // --------------------------------------------------------------------------- + /** The assert handler which is set by default. + * + * This issues a message to stderr and calls abort. + */ + ASSIMP_API void defaultAiAssertHandler(const char* failedExpression, const char* file, int line); + + // --------------------------------------------------------------------------- + /** Dispatches an assert violation to the assert handler. + */ + ASSIMP_API void aiAssertViolation(const char* failedExpression, const char* file, int line); +} // end of namespace Assimp + +#endif // INCLUDED_AI_ASSERTHANDLER_H \ No newline at end of file diff --git a/include/assimp/ai_assert.h b/include/assimp/ai_assert.h index f018163bf..6045a9801 100644 --- a/include/assimp/ai_assert.h +++ b/include/assimp/ai_assert.h @@ -42,14 +42,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_ASSERT_H_INC #define AI_ASSERT_H_INC -#ifdef __GNUC__ -# pragma GCC system_header -#endif +#if defined(ASSIMP_BUILD_DEBUG) || defined(ASSIMP_BUILD_WITH_ASSERTS) + +namespace Assimp +{ + void aiAssertViolation(const char* failedExpression, const char* file, int line); +} + +# define ai_assert(expression) (void)((!!(expression)) || (Assimp::aiAssertViolation(#expression, __FILE__, __LINE__), 0)) +# define ai_assert_entry() ai_assert(false) -#ifdef ASSIMP_BUILD_DEBUG -# include -# define ai_assert(expression) assert( expression ) -# define ai_assert_entry() assert( false ) #else # define ai_assert(expression) # define ai_assert_entry() diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index a5f8086e9..8e1746ce2 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -87,6 +87,7 @@ SET( COMMON unit/Common/uiScene.cpp unit/Common/utLineSplitter.cpp unit/Common/utSpatialSort.cpp + unit/Common/utAssertHandler.cpp ) SET( IMPORTERS diff --git a/test/unit/Common/utAssertHandler.cpp b/test/unit/Common/utAssertHandler.cpp new file mode 100644 index 000000000..0ac4c90af --- /dev/null +++ b/test/unit/Common/utAssertHandler.cpp @@ -0,0 +1,111 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2020, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +#include "UnitTestPCH.h" + +/// Ensure this test has asserts on, even if the build type doesn't have asserts by default. +#if !defined(ASSIMP_BUILD_WITH_ASSERTS) +#define ASSIMP_BUILD_WITH_ASSERTS +#endif + +#include +#include + +namespace +{ + /// An exception which is thrown by the testAssertHandler + struct TestAssertException : std::exception + { + TestAssertException(const char* failedExpression, const char* file, int line) + : std::exception("Test Assert Exception") + , m_failedExpression(failedExpression) + , m_file(file) + , m_line(line) + { + } + + std::string m_failedExpression; + std::string m_file; + int m_line; + }; + + /// Swap the default handler, which aborts, by one which throws. + void testAssertHandler(const char* failedExpression, const char* file, int line) + { + throw TestAssertException(failedExpression, file, line); + } + + /// Ensure that the default assert handler is restored after the test is finished. + struct ReplaceHandlerScope + { + ReplaceHandlerScope() + { + Assimp::setAiAssertHandler(testAssertHandler); + } + + ~ReplaceHandlerScope() + { + Assimp::setAiAssertHandler(Assimp::defaultAiAssertHandler); + } + }; +} + +TEST(utAssertHandler, replaceWithThrow) +{ + ReplaceHandlerScope scope; + + try + { + ai_assert((2 + 2 == 5) && "Sometimes people put messages here"); + EXPECT_TRUE(false); + } + catch(const TestAssertException& e) + { + EXPECT_STREQ(e.m_failedExpression.c_str(), "(2 + 2 == 5) && \"Sometimes people put messages here\""); + EXPECT_STREQ(e.m_file.c_str(), __FILE__); + EXPECT_GT(e.m_line, 0); + EXPECT_LT(e.m_line, __LINE__); + } + catch(...) + { + EXPECT_TRUE(false); + } +} From 297764335297053b86b273ad922d4459dda3e229 Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Tue, 23 Jun 2020 12:08:06 +0100 Subject: [PATCH 42/62] Fix. --- test/unit/Common/utAssertHandler.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test/unit/Common/utAssertHandler.cpp b/test/unit/Common/utAssertHandler.cpp index 0ac4c90af..d04162bdc 100644 --- a/test/unit/Common/utAssertHandler.cpp +++ b/test/unit/Common/utAssertHandler.cpp @@ -52,11 +52,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace { /// An exception which is thrown by the testAssertHandler - struct TestAssertException : std::exception + struct TestAssertException { TestAssertException(const char* failedExpression, const char* file, int line) - : std::exception("Test Assert Exception") - , m_failedExpression(failedExpression) + : m_failedExpression(failedExpression) , m_file(file) , m_line(line) { From ae05dbb2527da54e791e3a115975c3d06504093d Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 23 Jun 2020 21:11:18 +0200 Subject: [PATCH 43/62] define CheckValidFacesIndices also in release builds. --- code/AssetLib/glTF/glTFImporter.cpp | 403 +++++++++++++--------------- 1 file changed, 186 insertions(+), 217 deletions(-) diff --git a/code/AssetLib/glTF/glTFImporter.cpp b/code/AssetLib/glTF/glTFImporter.cpp index 33288313a..b4ef9b06f 100644 --- a/code/AssetLib/glTF/glTFImporter.cpp +++ b/code/AssetLib/glTF/glTFImporter.cpp @@ -48,12 +48,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -#include -#include #include -#include -#include #include +#include +#include +#include +#include #include @@ -69,8 +69,7 @@ static const aiImporterDesc desc = { "", "", "", - aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportBinaryFlavour | aiImporterFlags_SupportCompressedFlavour - | aiImporterFlags_LimitedSupport | aiImporterFlags_Experimental, + aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportBinaryFlavour | aiImporterFlags_SupportCompressedFlavour | aiImporterFlags_LimitedSupport | aiImporterFlags_Experimental, 0, 0, 0, @@ -78,11 +77,8 @@ static const aiImporterDesc desc = { "gltf glb" }; -glTFImporter::glTFImporter() -: BaseImporter() -, meshOffsets() -, embeddedTexIdxs() -, mScene( nullptr ) { +glTFImporter::glTFImporter() : + BaseImporter(), meshOffsets(), embeddedTexIdxs(), mScene(nullptr) { // empty } @@ -90,11 +86,11 @@ glTFImporter::~glTFImporter() { // empty } -const aiImporterDesc* glTFImporter::GetInfo() const { +const aiImporterDesc *glTFImporter::GetInfo() const { return &desc; } -bool glTFImporter::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool /* checkSig */) const { +bool glTFImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /* checkSig */) const { const std::string &extension = GetExtension(pFile); if (extension != "gltf" && extension != "glb") { @@ -115,9 +111,8 @@ bool glTFImporter::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool return false; } -inline -void SetMaterialColorProperty(std::vector& embeddedTexIdxs, Asset& /*r*/, glTF::TexProperty prop, aiMaterial* mat, - aiTextureType texType, const char* pKey, unsigned int type, unsigned int idx) { +inline void SetMaterialColorProperty(std::vector &embeddedTexIdxs, Asset & /*r*/, glTF::TexProperty prop, aiMaterial *mat, + aiTextureType texType, const char *pKey, unsigned int type, unsigned int idx) { if (prop.texture) { if (prop.texture->source) { aiString uri(prop.texture->source->uri); @@ -138,22 +133,22 @@ void SetMaterialColorProperty(std::vector& embeddedTexIdxs, Asset& /*r*/, g } } -void glTFImporter::ImportMaterials(glTF::Asset& r) { +void glTFImporter::ImportMaterials(glTF::Asset &r) { mScene->mNumMaterials = unsigned(r.materials.Size()); - mScene->mMaterials = new aiMaterial*[mScene->mNumMaterials]; + mScene->mMaterials = new aiMaterial *[mScene->mNumMaterials]; for (unsigned int i = 0; i < mScene->mNumMaterials; ++i) { - aiMaterial* aimat = mScene->mMaterials[i] = new aiMaterial(); + aiMaterial *aimat = mScene->mMaterials[i] = new aiMaterial(); - Material& mat = r.materials[i]; + Material &mat = r.materials[i]; /*if (!mat.name.empty())*/ { aiString str(mat.id /*mat.name*/); aimat->AddProperty(&str, AI_MATKEY_NAME); } - SetMaterialColorProperty(embeddedTexIdxs, r, mat.ambient, aimat, aiTextureType_AMBIENT, AI_MATKEY_COLOR_AMBIENT ); - SetMaterialColorProperty(embeddedTexIdxs, r, mat.diffuse, aimat, aiTextureType_DIFFUSE, AI_MATKEY_COLOR_DIFFUSE ); + SetMaterialColorProperty(embeddedTexIdxs, r, mat.ambient, aimat, aiTextureType_AMBIENT, AI_MATKEY_COLOR_AMBIENT); + SetMaterialColorProperty(embeddedTexIdxs, r, mat.diffuse, aimat, aiTextureType_DIFFUSE, AI_MATKEY_COLOR_DIFFUSE); SetMaterialColorProperty(embeddedTexIdxs, r, mat.specular, aimat, aiTextureType_SPECULAR, AI_MATKEY_COLOR_SPECULAR); SetMaterialColorProperty(embeddedTexIdxs, r, mat.emission, aimat, aiTextureType_EMISSIVE, AI_MATKEY_COLOR_EMISSIVE); @@ -172,29 +167,25 @@ void glTFImporter::ImportMaterials(glTF::Asset& r) { mScene->mNumMaterials = 1; // Delete the array of length zero created above. delete[] mScene->mMaterials; - mScene->mMaterials = new aiMaterial*[1]; + mScene->mMaterials = new aiMaterial *[1]; mScene->mMaterials[0] = new aiMaterial(); } } - -static inline void SetFace(aiFace& face, int a) -{ +static inline void SetFace(aiFace &face, int a) { face.mNumIndices = 1; face.mIndices = new unsigned int[1]; face.mIndices[0] = a; } -static inline void SetFace(aiFace& face, int a, int b) -{ +static inline void SetFace(aiFace &face, int a, int b) { face.mNumIndices = 2; face.mIndices = new unsigned int[2]; face.mIndices[0] = a; face.mIndices[1] = b; } -static inline void SetFace(aiFace& face, int a, int b, int c) -{ +static inline void SetFace(aiFace &face, int a, int b, int c) { face.mNumIndices = 3; face.mIndices = new unsigned int[3]; face.mIndices[0] = a; @@ -202,9 +193,7 @@ static inline void SetFace(aiFace& face, int a, int b, int c) face.mIndices[2] = c; } -#ifdef ASSIMP_BUILD_DEBUG -static inline bool CheckValidFacesIndices(aiFace* faces, unsigned nFaces, unsigned nVerts) -{ +static inline bool CheckValidFacesIndices(aiFace *faces, unsigned nFaces, unsigned nVerts) { for (unsigned i = 0; i < nFaces; ++i) { for (unsigned j = 0; j < faces[i].mNumIndices; ++j) { unsigned idx = faces[i].mIndices[j]; @@ -214,105 +203,98 @@ static inline bool CheckValidFacesIndices(aiFace* faces, unsigned nFaces, unsign } return true; } -#endif // ASSIMP_BUILD_DEBUG -void glTFImporter::ImportMeshes(glTF::Asset& r) -{ - std::vector meshes; +void glTFImporter::ImportMeshes(glTF::Asset &r) { + std::vector meshes; unsigned int k = 0; meshOffsets.clear(); for (unsigned int m = 0; m < r.meshes.Size(); ++m) { - Mesh& mesh = r.meshes[m]; + Mesh &mesh = r.meshes[m]; - // Check if mesh extensions is used - if(mesh.Extension.size() > 0) - { - for(Mesh::SExtension* cur_ext : mesh.Extension) - { + // Check if mesh extensions is used + if (mesh.Extension.size() > 0) { + for (Mesh::SExtension *cur_ext : mesh.Extension) { #ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC - if(cur_ext->Type == Mesh::SExtension::EType::Compression_Open3DGC) - { - // Limitations for meshes when using Open3DGC-compression. - // It's a current limitation of sp... Specification have not this part still - about mesh compression. Why only one primitive? - // Because glTF is very flexibly. But in fact it ugly flexible. Every primitive can has own set of accessors and accessors can - // point to a-a-a-a-any part of buffer (through bufferview of course) and even to another buffer. We know that "Open3DGC-compression" - // is applicable only to part of buffer. As we can't guaranty continuity of the data for decoder, we will limit quantity of primitives. - // Yes indices, coordinates etc. still can br stored in different buffers, but with current specification it's a exporter problem. - // Also primitive can has only one of "POSITION", "NORMAL" and less then "AI_MAX_NUMBER_OF_TEXTURECOORDS" of "TEXCOORD". All accessor - // of primitive must point to one continuous region of the buffer. - if(mesh.primitives.size() > 2) throw DeadlyImportError("GLTF: When using Open3DGC compression then only one primitive per mesh are allowed."); + if (cur_ext->Type == Mesh::SExtension::EType::Compression_Open3DGC) { + // Limitations for meshes when using Open3DGC-compression. + // It's a current limitation of sp... Specification have not this part still - about mesh compression. Why only one primitive? + // Because glTF is very flexibly. But in fact it ugly flexible. Every primitive can has own set of accessors and accessors can + // point to a-a-a-a-any part of buffer (through bufferview of course) and even to another buffer. We know that "Open3DGC-compression" + // is applicable only to part of buffer. As we can't guaranty continuity of the data for decoder, we will limit quantity of primitives. + // Yes indices, coordinates etc. still can br stored in different buffers, but with current specification it's a exporter problem. + // Also primitive can has only one of "POSITION", "NORMAL" and less then "AI_MAX_NUMBER_OF_TEXTURECOORDS" of "TEXCOORD". All accessor + // of primitive must point to one continuous region of the buffer. + if (mesh.primitives.size() > 2) throw DeadlyImportError("GLTF: When using Open3DGC compression then only one primitive per mesh are allowed."); - Mesh::SCompression_Open3DGC* o3dgc_ext = (Mesh::SCompression_Open3DGC*)cur_ext; - Ref buf = r.buffers.Get(o3dgc_ext->Buffer); + Mesh::SCompression_Open3DGC *o3dgc_ext = (Mesh::SCompression_Open3DGC *)cur_ext; + Ref buf = r.buffers.Get(o3dgc_ext->Buffer); - buf->EncodedRegion_SetCurrent(mesh.id); - } - else + buf->EncodedRegion_SetCurrent(mesh.id); + } else #endif - { - throw DeadlyImportError("GLTF: Can not import mesh: unknown mesh extension (code: \"" + to_string(cur_ext->Type) + - "\"), only Open3DGC is supported."); - } - } - }// if(mesh.Extension.size() > 0) + { + throw DeadlyImportError("GLTF: Can not import mesh: unknown mesh extension (code: \"" + to_string(cur_ext->Type) + + "\"), only Open3DGC is supported."); + } + } + } // if(mesh.Extension.size() > 0) - meshOffsets.push_back(k); + meshOffsets.push_back(k); k += unsigned(mesh.primitives.size()); for (unsigned int p = 0; p < mesh.primitives.size(); ++p) { - Mesh::Primitive& prim = mesh.primitives[p]; + Mesh::Primitive &prim = mesh.primitives[p]; - aiMesh* aim = new aiMesh(); + aiMesh *aim = new aiMesh(); meshes.push_back(aim); aim->mName = mesh.id; if (mesh.primitives.size() > 1) { - ai_uint32& len = aim->mName.length; + ai_uint32 &len = aim->mName.length; aim->mName.data[len] = '-'; len += 1 + ASSIMP_itoa10(aim->mName.data + len + 1, unsigned(MAXLEN - len - 1), p); } switch (prim.mode) { - case PrimitiveMode_POINTS: - aim->mPrimitiveTypes |= aiPrimitiveType_POINT; - break; + case PrimitiveMode_POINTS: + aim->mPrimitiveTypes |= aiPrimitiveType_POINT; + break; - case PrimitiveMode_LINES: - case PrimitiveMode_LINE_LOOP: - case PrimitiveMode_LINE_STRIP: - aim->mPrimitiveTypes |= aiPrimitiveType_LINE; - break; + case PrimitiveMode_LINES: + case PrimitiveMode_LINE_LOOP: + case PrimitiveMode_LINE_STRIP: + aim->mPrimitiveTypes |= aiPrimitiveType_LINE; + break; - case PrimitiveMode_TRIANGLES: - case PrimitiveMode_TRIANGLE_STRIP: - case PrimitiveMode_TRIANGLE_FAN: - aim->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE; - break; + case PrimitiveMode_TRIANGLES: + case PrimitiveMode_TRIANGLE_STRIP: + case PrimitiveMode_TRIANGLE_FAN: + aim->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE; + break; } - Mesh::Primitive::Attributes& attr = prim.attributes; + Mesh::Primitive::Attributes &attr = prim.attributes; - if (attr.position.size() > 0 && attr.position[0]) { + if (attr.position.size() > 0 && attr.position[0]) { aim->mNumVertices = attr.position[0]->count; attr.position[0]->ExtractData(aim->mVertices); - } + } - if (attr.normal.size() > 0 && attr.normal[0]) attr.normal[0]->ExtractData(aim->mNormals); + if (attr.normal.size() > 0 && attr.normal[0]) attr.normal[0]->ExtractData(aim->mNormals); for (size_t tc = 0; tc < attr.texcoord.size() && tc < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++tc) { attr.texcoord[tc]->ExtractData(aim->mTextureCoords[tc]); aim->mNumUVComponents[tc] = attr.texcoord[tc]->GetNumComponents(); - aiVector3D* values = aim->mTextureCoords[tc]; + aiVector3D *values = aim->mTextureCoords[tc]; for (unsigned int i = 0; i < aim->mNumVertices; ++i) { values[i].y = 1 - values[i].y; // Flip Y coords } } - - aiFace* faces = 0; + aiFace *faces = 0; unsigned int nFaces = 0; if (prim.indices) { @@ -322,76 +304,75 @@ void glTFImporter::ImportMeshes(glTF::Asset& r) ai_assert(data.IsValid()); switch (prim.mode) { - case PrimitiveMode_POINTS: { - nFaces = count; - faces = new aiFace[nFaces]; - for (unsigned int i = 0; i < count; ++i) { - SetFace(faces[i], data.GetUInt(i)); - } - break; + case PrimitiveMode_POINTS: { + nFaces = count; + faces = new aiFace[nFaces]; + for (unsigned int i = 0; i < count; ++i) { + SetFace(faces[i], data.GetUInt(i)); } - - case PrimitiveMode_LINES: { - nFaces = count / 2; - if (nFaces * 2 != count) { - ASSIMP_LOG_WARN("The number of vertices was not compatible with the LINES mode. Some vertices were dropped."); - count = nFaces * 2; - } - faces = new aiFace[nFaces]; - for (unsigned int i = 0; i < count; i += 2) { - SetFace(faces[i / 2], data.GetUInt(i), data.GetUInt(i + 1)); - } - break; - } - - case PrimitiveMode_LINE_LOOP: - case PrimitiveMode_LINE_STRIP: { - nFaces = count - ((prim.mode == PrimitiveMode_LINE_STRIP) ? 1 : 0); - faces = new aiFace[nFaces]; - SetFace(faces[0], data.GetUInt(0), data.GetUInt(1)); - for (unsigned int i = 2; i < count; ++i) { - SetFace(faces[i - 1], faces[i - 2].mIndices[1], data.GetUInt(i)); - } - if (prim.mode == PrimitiveMode_LINE_LOOP) { // close the loop - SetFace(faces[count - 1], faces[count - 2].mIndices[1], faces[0].mIndices[0]); - } - break; - } - - case PrimitiveMode_TRIANGLES: { - nFaces = count / 3; - if (nFaces * 3 != count) { - ASSIMP_LOG_WARN("The number of vertices was not compatible with the TRIANGLES mode. Some vertices were dropped."); - count = nFaces * 3; - } - faces = new aiFace[nFaces]; - for (unsigned int i = 0; i < count; i += 3) { - SetFace(faces[i / 3], data.GetUInt(i), data.GetUInt(i + 1), data.GetUInt(i + 2)); - } - break; - } - case PrimitiveMode_TRIANGLE_STRIP: { - nFaces = count - 2; - faces = new aiFace[nFaces]; - SetFace(faces[0], data.GetUInt(0), data.GetUInt(1), data.GetUInt(2)); - for (unsigned int i = 3; i < count; ++i) { - SetFace(faces[i - 2], faces[i - 1].mIndices[1], faces[i - 1].mIndices[2], data.GetUInt(i)); - } - break; - } - case PrimitiveMode_TRIANGLE_FAN: - nFaces = count - 2; - faces = new aiFace[nFaces]; - SetFace(faces[0], data.GetUInt(0), data.GetUInt(1), data.GetUInt(2)); - for (unsigned int i = 3; i < count; ++i) { - SetFace(faces[i - 2], faces[0].mIndices[0], faces[i - 1].mIndices[2], data.GetUInt(i)); - } - break; + break; } - } - else { // no indices provided so directly generate from counts - // use the already determined count as it includes checks + case PrimitiveMode_LINES: { + nFaces = count / 2; + if (nFaces * 2 != count) { + ASSIMP_LOG_WARN("The number of vertices was not compatible with the LINES mode. Some vertices were dropped."); + count = nFaces * 2; + } + faces = new aiFace[nFaces]; + for (unsigned int i = 0; i < count; i += 2) { + SetFace(faces[i / 2], data.GetUInt(i), data.GetUInt(i + 1)); + } + break; + } + + case PrimitiveMode_LINE_LOOP: + case PrimitiveMode_LINE_STRIP: { + nFaces = count - ((prim.mode == PrimitiveMode_LINE_STRIP) ? 1 : 0); + faces = new aiFace[nFaces]; + SetFace(faces[0], data.GetUInt(0), data.GetUInt(1)); + for (unsigned int i = 2; i < count; ++i) { + SetFace(faces[i - 1], faces[i - 2].mIndices[1], data.GetUInt(i)); + } + if (prim.mode == PrimitiveMode_LINE_LOOP) { // close the loop + SetFace(faces[count - 1], faces[count - 2].mIndices[1], faces[0].mIndices[0]); + } + break; + } + + case PrimitiveMode_TRIANGLES: { + nFaces = count / 3; + if (nFaces * 3 != count) { + ASSIMP_LOG_WARN("The number of vertices was not compatible with the TRIANGLES mode. Some vertices were dropped."); + count = nFaces * 3; + } + faces = new aiFace[nFaces]; + for (unsigned int i = 0; i < count; i += 3) { + SetFace(faces[i / 3], data.GetUInt(i), data.GetUInt(i + 1), data.GetUInt(i + 2)); + } + break; + } + case PrimitiveMode_TRIANGLE_STRIP: { + nFaces = count - 2; + faces = new aiFace[nFaces]; + SetFace(faces[0], data.GetUInt(0), data.GetUInt(1), data.GetUInt(2)); + for (unsigned int i = 3; i < count; ++i) { + SetFace(faces[i - 2], faces[i - 1].mIndices[1], faces[i - 1].mIndices[2], data.GetUInt(i)); + } + break; + } + case PrimitiveMode_TRIANGLE_FAN: + nFaces = count - 2; + faces = new aiFace[nFaces]; + SetFace(faces[0], data.GetUInt(0), data.GetUInt(1), data.GetUInt(2)); + for (unsigned int i = 3; i < count; ++i) { + SetFace(faces[i - 2], faces[0].mIndices[0], faces[i - 1].mIndices[2], data.GetUInt(i)); + } + break; + } + } else { // no indices provided so directly generate from counts + + // use the already determined count as it includes checks unsigned int count = aim->mNumVertices; switch (prim.mode) { @@ -484,22 +465,22 @@ void glTFImporter::ImportMeshes(glTF::Asset& r) CopyVector(meshes, mScene->mMeshes, mScene->mNumMeshes); } -void glTFImporter::ImportCameras(glTF::Asset& r) { +void glTFImporter::ImportCameras(glTF::Asset &r) { if (!r.cameras.Size()) { return; } mScene->mNumCameras = r.cameras.Size(); - mScene->mCameras = new aiCamera*[r.cameras.Size()]; + mScene->mCameras = new aiCamera *[r.cameras.Size()]; for (size_t i = 0; i < r.cameras.Size(); ++i) { - Camera& cam = r.cameras[i]; + Camera &cam = r.cameras[i]; - aiCamera* aicam = mScene->mCameras[i] = new aiCamera(); + aiCamera *aicam = mScene->mCameras[i] = new aiCamera(); if (cam.type == Camera::Perspective) { - aicam->mAspect = cam.perspective.aspectRatio; + aicam->mAspect = cam.perspective.aspectRatio; aicam->mHorizontalFOV = cam.perspective.yfov * ((aicam->mAspect == 0.f) ? 1.f : aicam->mAspect); - aicam->mClipPlaneFar = cam.perspective.zfar; + aicam->mClipPlaneFar = cam.perspective.zfar; aicam->mClipPlaneNear = cam.perspective.znear; } else { aicam->mClipPlaneFar = cam.ortographic.zfar; @@ -513,30 +494,33 @@ void glTFImporter::ImportCameras(glTF::Asset& r) { } } -void glTFImporter::ImportLights(glTF::Asset& r) -{ +void glTFImporter::ImportLights(glTF::Asset &r) { if (!r.lights.Size()) return; mScene->mNumLights = r.lights.Size(); - mScene->mLights = new aiLight*[r.lights.Size()]; + mScene->mLights = new aiLight *[r.lights.Size()]; for (size_t i = 0; i < r.lights.Size(); ++i) { - Light& l = r.lights[i]; + Light &l = r.lights[i]; - aiLight* ail = mScene->mLights[i] = new aiLight(); + aiLight *ail = mScene->mLights[i] = new aiLight(); switch (l.type) { - case Light::Type_directional: - ail->mType = aiLightSource_DIRECTIONAL; break; + case Light::Type_directional: + ail->mType = aiLightSource_DIRECTIONAL; + break; - case Light::Type_spot: - ail->mType = aiLightSource_SPOT; break; + case Light::Type_spot: + ail->mType = aiLightSource_SPOT; + break; - case Light::Type_ambient: - ail->mType = aiLightSource_AMBIENT; break; + case Light::Type_ambient: + ail->mType = aiLightSource_AMBIENT; + break; - default: // Light::Type_point - ail->mType = aiLightSource_POINT; break; + default: // Light::Type_point + ail->mType = aiLightSource_POINT; + break; } CopyValue(l.color, ail->mColorAmbient); @@ -546,35 +530,32 @@ void glTFImporter::ImportLights(glTF::Asset& r) ail->mAngleOuterCone = l.falloffAngle; ail->mAngleInnerCone = l.falloffExponent; // TODO fix this, it does not look right at all - ail->mAttenuationConstant = l.constantAttenuation; - ail->mAttenuationLinear = l.linearAttenuation; + ail->mAttenuationConstant = l.constantAttenuation; + ail->mAttenuationLinear = l.linearAttenuation; ail->mAttenuationQuadratic = l.quadraticAttenuation; } } +aiNode *ImportNode(aiScene *pScene, glTF::Asset &r, std::vector &meshOffsets, glTF::Ref &ptr) { + Node &node = *ptr; -aiNode* ImportNode(aiScene* pScene, glTF::Asset& r, std::vector& meshOffsets, glTF::Ref& ptr) -{ - Node& node = *ptr; - - aiNode* ainode = new aiNode(node.id); + aiNode *ainode = new aiNode(node.id); if (!node.children.empty()) { ainode->mNumChildren = unsigned(node.children.size()); - ainode->mChildren = new aiNode*[ainode->mNumChildren]; + ainode->mChildren = new aiNode *[ainode->mNumChildren]; for (unsigned int i = 0; i < ainode->mNumChildren; ++i) { - aiNode* child = ImportNode(pScene, r, meshOffsets, node.children[i]); + aiNode *child = ImportNode(pScene, r, meshOffsets, node.children[i]); child->mParent = ainode; ainode->mChildren[i] = child; } } - aiMatrix4x4& matrix = ainode->mTransformation; + aiMatrix4x4 &matrix = ainode->mTransformation; if (node.matrix.isPresent) { CopyValue(node.matrix.value, matrix); - } - else { + } else { if (node.translation.isPresent) { aiVector3D trans; CopyValue(node.translation.value, trans); @@ -591,7 +572,6 @@ aiNode* ImportNode(aiScene* pScene, glTF::Asset& r, std::vector& m matrix = s * matrix; } - if (node.rotation.isPresent) { aiQuaternion rot; CopyValue(node.rotation.value, rot); @@ -629,22 +609,20 @@ aiNode* ImportNode(aiScene* pScene, glTF::Asset& r, std::vector& m return ainode; } -void glTFImporter::ImportNodes(glTF::Asset& r) -{ +void glTFImporter::ImportNodes(glTF::Asset &r) { if (!r.scene) return; - std::vector< Ref > rootNodes = r.scene->nodes; + std::vector> rootNodes = r.scene->nodes; // The root nodes unsigned int numRootNodes = unsigned(rootNodes.size()); if (numRootNodes == 1) { // a single root node: use it mScene->mRootNode = ImportNode(mScene, r, meshOffsets, rootNodes[0]); - } - else if (numRootNodes > 1) { // more than one root node: create a fake root - aiNode* root = new aiNode("ROOT"); - root->mChildren = new aiNode*[numRootNodes]; + } else if (numRootNodes > 1) { // more than one root node: create a fake root + aiNode *root = new aiNode("ROOT"); + root->mChildren = new aiNode *[numRootNodes]; for (unsigned int i = 0; i < numRootNodes; ++i) { - aiNode* node = ImportNode(mScene, r, meshOffsets, rootNodes[i]); + aiNode *node = ImportNode(mScene, r, meshOffsets, rootNodes[i]); node->mParent = root; root->mChildren[root->mNumChildren++] = node; } @@ -656,8 +634,7 @@ void glTFImporter::ImportNodes(glTF::Asset& r) //} } -void glTFImporter::ImportEmbeddedTextures(glTF::Asset& r) -{ +void glTFImporter::ImportEmbeddedTextures(glTF::Asset &r) { embeddedTexIdxs.resize(r.images.Size(), -1); int numEmbeddedTexs = 0; @@ -669,7 +646,7 @@ void glTFImporter::ImportEmbeddedTextures(glTF::Asset& r) if (numEmbeddedTexs == 0) return; - mScene->mTextures = new aiTexture*[numEmbeddedTexs]; + mScene->mTextures = new aiTexture *[numEmbeddedTexs]; // Add the embedded textures for (size_t i = 0; i < r.images.Size(); ++i) { @@ -679,18 +656,18 @@ void glTFImporter::ImportEmbeddedTextures(glTF::Asset& r) int idx = mScene->mNumTextures++; embeddedTexIdxs[i] = idx; - aiTexture* tex = mScene->mTextures[idx] = new aiTexture(); + aiTexture *tex = mScene->mTextures[idx] = new aiTexture(); size_t length = img.GetDataLength(); - void* data = img.StealData(); + void *data = img.StealData(); tex->mFilename = img.name; tex->mWidth = static_cast(length); tex->mHeight = 0; - tex->pcData = reinterpret_cast(data); + tex->pcData = reinterpret_cast(data); if (!img.mimeType.empty()) { - const char* ext = strchr(img.mimeType.c_str(), '/') + 1; + const char *ext = strchr(img.mimeType.c_str(), '/') + 1; if (ext) { if (strcmp(ext, "jpeg") == 0) ext = "jpg"; @@ -703,32 +680,26 @@ void glTFImporter::ImportEmbeddedTextures(glTF::Asset& r) } } -void glTFImporter::ImportCommonMetadata(glTF::Asset& a) -{ +void glTFImporter::ImportCommonMetadata(glTF::Asset &a) { ai_assert(mScene->mMetaData == nullptr); const bool hasVersion = !a.asset.version.empty(); const bool hasGenerator = !a.asset.generator.empty(); const bool hasCopyright = !a.asset.copyright.empty(); - if (hasVersion || hasGenerator || hasCopyright) - { + if (hasVersion || hasGenerator || hasCopyright) { mScene->mMetaData = new aiMetadata; - if (hasVersion) - { + if (hasVersion) { mScene->mMetaData->Add(AI_METADATA_SOURCE_FORMAT_VERSION, aiString(a.asset.version)); } - if (hasGenerator) - { + if (hasGenerator) { mScene->mMetaData->Add(AI_METADATA_SOURCE_GENERATOR, aiString(a.asset.generator)); } - if (hasCopyright) - { + if (hasCopyright) { mScene->mMetaData->Add(AI_METADATA_SOURCE_COPYRIGHT, aiString(a.asset.copyright)); } } } -void glTFImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) -{ +void glTFImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) { // clean all member arrays meshOffsets.clear(); embeddedTexIdxs.clear(); @@ -739,7 +710,6 @@ void glTFImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOS glTF::Asset asset(pIOHandler); asset.Load(pFile, GetExtension(pFile) == "glb"); - // // Copy the data out // @@ -761,4 +731,3 @@ void glTFImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOS } #endif // ASSIMP_BUILD_NO_GLTF_IMPORTER - From edaa8e4a802ed9943e04500a64046661b56e94ef Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Wed, 24 Jun 2020 11:37:43 +0100 Subject: [PATCH 44/62] Need to use ASSIMP_BUILD_DEBUG. --- include/assimp/ai_assert.h | 2 +- test/unit/Common/utAssertHandler.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/assimp/ai_assert.h b/include/assimp/ai_assert.h index 6045a9801..320104cfb 100644 --- a/include/assimp/ai_assert.h +++ b/include/assimp/ai_assert.h @@ -42,7 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_ASSERT_H_INC #define AI_ASSERT_H_INC -#if defined(ASSIMP_BUILD_DEBUG) || defined(ASSIMP_BUILD_WITH_ASSERTS) +#if defined(ASSIMP_BUILD_DEBUG) namespace Assimp { diff --git a/test/unit/Common/utAssertHandler.cpp b/test/unit/Common/utAssertHandler.cpp index d04162bdc..4a567c0c3 100644 --- a/test/unit/Common/utAssertHandler.cpp +++ b/test/unit/Common/utAssertHandler.cpp @@ -42,8 +42,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "UnitTestPCH.h" /// Ensure this test has asserts on, even if the build type doesn't have asserts by default. -#if !defined(ASSIMP_BUILD_WITH_ASSERTS) -#define ASSIMP_BUILD_WITH_ASSERTS +#if !defined(ASSIMP_BUILD_DEBUG) +#define ASSIMP_BUILD_DEBUG #endif #include From 170c00eee7120938ec6f2ef770b6e9a383d4dcda Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Wed, 24 Jun 2020 11:51:03 +0100 Subject: [PATCH 45/62] Useful comment. --- include/assimp/ai_assert.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/assimp/ai_assert.h b/include/assimp/ai_assert.h index 320104cfb..8b2b396f4 100644 --- a/include/assimp/ai_assert.h +++ b/include/assimp/ai_assert.h @@ -46,6 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace Assimp { + // Assert violation behavior can be customized: see AssertHandler.h. void aiAssertViolation(const char* failedExpression, const char* file, int line); } From 1466bbacf87ce6996a9c934668f8df3b08a7fef5 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 24 Jun 2020 20:30:02 +0200 Subject: [PATCH 46/62] fix unittests. --- code/AssetLib/MD5/MD5Loader.cpp | 145 ++++++++++++++++++-------------- code/AssetLib/MD5/MD5Loader.h | 15 ++-- 2 files changed, 87 insertions(+), 73 deletions(-) diff --git a/code/AssetLib/MD5/MD5Loader.cpp b/code/AssetLib/MD5/MD5Loader.cpp index 1790eac2a..5428a9c74 100644 --- a/code/AssetLib/MD5/MD5Loader.cpp +++ b/code/AssetLib/MD5/MD5Loader.cpp @@ -5,8 +5,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2020, assimp team - - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -82,7 +80,15 @@ static const aiImporterDesc desc = { // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer MD5Importer::MD5Importer() : - mIOHandler(nullptr), mBuffer(), fileSize(), iLineNumber(), pScene(), bHadMD5Mesh(), bHadMD5Anim(), bHadMD5Camera(), configNoAutoLoad(false) { + mIOHandler(nullptr), + mBuffer(), + mFileSize(), + mLineNumber(), + mScene(), + mHadMD5Mesh(), + mHadMD5Anim(), + mHadMD5Camera(), + mCconfigNoAutoLoad(false) { // empty } @@ -106,6 +112,7 @@ bool MD5Importer::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool c const char *tokens[] = { "MD5Version" }; return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1); } + return false; } @@ -119,16 +126,15 @@ const aiImporterDesc *MD5Importer::GetInfo() const { // Setup import properties void MD5Importer::SetupProperties(const Importer *pImp) { // AI_CONFIG_IMPORT_MD5_NO_ANIM_AUTOLOAD - configNoAutoLoad = (0 != pImp->GetPropertyInteger(AI_CONFIG_IMPORT_MD5_NO_ANIM_AUTOLOAD, 0)); + mCconfigNoAutoLoad = (0 != pImp->GetPropertyInteger(AI_CONFIG_IMPORT_MD5_NO_ANIM_AUTOLOAD, 0)); } // ------------------------------------------------------------------------------------------------ // Imports the given file into the given scene structure. -void MD5Importer::InternReadFile(const std::string &pFile, - aiScene *_pScene, IOSystem *pIOHandler) { +void MD5Importer::InternReadFile(const std::string &pFile, aiScene *_pScene, IOSystem *pIOHandler) { mIOHandler = pIOHandler; - pScene = _pScene; - bHadMD5Mesh = bHadMD5Anim = bHadMD5Camera = false; + mScene = _pScene; + mHadMD5Mesh = mHadMD5Anim = mHadMD5Camera = false; // remove the file extension const std::string::size_type pos = pFile.find_last_of('.'); @@ -138,7 +144,7 @@ void MD5Importer::InternReadFile(const std::string &pFile, try { if (extension == "md5camera") { LoadMD5CameraFile(); - } else if (configNoAutoLoad || extension == "md5anim") { + } else if (mCconfigNoAutoLoad || extension == "md5anim") { // determine file extension and process just *one* file if (extension.length() == 0) { throw DeadlyImportError("Failure, need file extension to determine MD5 part type"); @@ -158,17 +164,17 @@ void MD5Importer::InternReadFile(const std::string &pFile, } // make sure we have at least one file - if (!bHadMD5Mesh && !bHadMD5Anim && !bHadMD5Camera) { + if (!mHadMD5Mesh && !mHadMD5Anim && !mHadMD5Camera) { throw DeadlyImportError("Failed to read valid contents out of this MD5* file"); } // Now rotate the whole scene 90 degrees around the x axis to match our internal coordinate system - pScene->mRootNode->mTransformation = aiMatrix4x4(1.f, 0.f, 0.f, 0.f, + mScene->mRootNode->mTransformation = aiMatrix4x4(1.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, -1.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f); // the output scene wouldn't pass the validation without this flag - if (!bHadMD5Mesh) { - pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE; + if (!mHadMD5Mesh) { + mScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE; } // clean the instance -- the BaseImporter instance may be reused later. @@ -182,16 +188,16 @@ void MD5Importer::LoadFileIntoMemory(IOStream *file) { UnloadFileFromMemory(); ai_assert(nullptr != file); - fileSize = (unsigned int)file->FileSize(); - ai_assert(fileSize); + mFileSize = (unsigned int)file->FileSize(); + ai_assert(mFileSize); // allocate storage and copy the contents of the file to a memory buffer - mBuffer = new char[fileSize + 1]; - file->Read((void *)mBuffer, 1, fileSize); - iLineNumber = 1; + mBuffer = new char[mFileSize + 1]; + file->Read((void *)mBuffer, 1, mFileSize); + mLineNumber = 1; // append a terminal 0 - mBuffer[fileSize] = '\0'; + mBuffer[mFileSize] = '\0'; // now remove all line comments from the file CommentRemover::RemoveLineComments("//", mBuffer, ' '); @@ -203,7 +209,7 @@ void MD5Importer::UnloadFileFromMemory() { // delete the file buffer delete[] mBuffer; mBuffer = nullptr; - fileSize = 0; + mFileSize = 0; } // ------------------------------------------------------------------------------------------------ @@ -339,31 +345,32 @@ void MD5Importer::LoadMD5MeshFile() { // Check whether we can read from the file if (file.get() == nullptr || !file->FileSize()) { - throw DeadlyImportError("Failed to open MD5 file " + filename + "."); + ASSIMP_LOG_WARN("Failed to access MD5MESH file: " + filename); + return; } - bHadMD5Mesh = true; + mHadMD5Mesh = true; LoadFileIntoMemory(file.get()); // now construct a parser and parse the file - MD5::MD5Parser parser(mBuffer, fileSize); + MD5::MD5Parser parser(mBuffer, mFileSize); // load the mesh information from it MD5::MD5MeshParser meshParser(parser.mSections); // create the bone hierarchy - first the root node and dummy nodes for all meshes - pScene->mRootNode = new aiNode(""); - pScene->mRootNode->mNumChildren = 2; - pScene->mRootNode->mChildren = new aiNode *[2]; + mScene->mRootNode = new aiNode(""); + mScene->mRootNode->mNumChildren = 2; + mScene->mRootNode->mChildren = new aiNode *[2]; // build the hierarchy from the MD5MESH file - aiNode *pcNode = pScene->mRootNode->mChildren[1] = new aiNode(); + aiNode *pcNode = mScene->mRootNode->mChildren[1] = new aiNode(); pcNode->mName.Set(""); - pcNode->mParent = pScene->mRootNode; + pcNode->mParent = mScene->mRootNode; AttachChilds_Mesh(-1, pcNode, meshParser.mJoints); - pcNode = pScene->mRootNode->mChildren[0] = new aiNode(); + pcNode = mScene->mRootNode->mChildren[0] = new aiNode(); pcNode->mName.Set(""); - pcNode->mParent = pScene->mRootNode; + pcNode->mParent = mScene->mRootNode; #if 0 if (pScene->mRootNode->mChildren[1]->mNumChildren) /* start at the right hierarchy level */ @@ -372,28 +379,31 @@ void MD5Importer::LoadMD5MeshFile() { // FIX: MD5 files exported from Blender can have empty meshes for (std::vector::const_iterator it = meshParser.mMeshes.begin(), end = meshParser.mMeshes.end(); it != end; ++it) { - if (!(*it).mFaces.empty() && !(*it).mVertices.empty()) - ++pScene->mNumMaterials; + if (!(*it).mFaces.empty() && !(*it).mVertices.empty()) { + ++mScene->mNumMaterials; + } } // generate all meshes - pScene->mNumMeshes = pScene->mNumMaterials; - pScene->mMeshes = new aiMesh *[pScene->mNumMeshes]; - pScene->mMaterials = new aiMaterial *[pScene->mNumMeshes]; + mScene->mNumMeshes = mScene->mNumMaterials; + mScene->mMeshes = new aiMesh *[mScene->mNumMeshes]; + mScene->mMaterials = new aiMaterial *[mScene->mNumMeshes]; // storage for node mesh indices - pcNode->mNumMeshes = pScene->mNumMeshes; + pcNode->mNumMeshes = mScene->mNumMeshes; pcNode->mMeshes = new unsigned int[pcNode->mNumMeshes]; - for (unsigned int m = 0; m < pcNode->mNumMeshes; ++m) + for (unsigned int m = 0; m < pcNode->mNumMeshes; ++m) { pcNode->mMeshes[m] = m; + } unsigned int n = 0; for (std::vector::iterator it = meshParser.mMeshes.begin(), end = meshParser.mMeshes.end(); it != end; ++it) { MD5::MeshDesc &meshSrc = *it; - if (meshSrc.mFaces.empty() || meshSrc.mVertices.empty()) + if (meshSrc.mFaces.empty() || meshSrc.mVertices.empty()) { continue; + } - aiMesh *mesh = pScene->mMeshes[n] = new aiMesh(); + aiMesh *mesh = mScene->mMeshes[n] = new aiMesh(); mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; // generate unique vertices in our internal verbose format @@ -423,17 +433,19 @@ void MD5Importer::LoadMD5MeshFile() { for (unsigned int jub = (*iter).mFirstWeight, w = jub; w < jub + (*iter).mNumWeights; ++w) { MD5::WeightDesc &weightDesc = meshSrc.mWeights[w]; /* FIX for some invalid exporters */ - if (!(weightDesc.mWeight < AI_MD5_WEIGHT_EPSILON && weightDesc.mWeight >= -AI_MD5_WEIGHT_EPSILON)) + if (!(weightDesc.mWeight < AI_MD5_WEIGHT_EPSILON && weightDesc.mWeight >= -AI_MD5_WEIGHT_EPSILON)) { ++piCount[weightDesc.mBone]; + } } } // check how many we will need - for (unsigned int p = 0; p < meshParser.mJoints.size(); ++p) + for (unsigned int p = 0; p < meshParser.mJoints.size(); ++p) { if (piCount[p]) mesh->mNumBones++; + } - if (mesh->mNumBones) // just for safety - { + // just for safety + if (mesh->mNumBones) { mesh->mBones = new aiBone *[mesh->mNumBones]; for (unsigned int q = 0, h = 0; q < meshParser.mJoints.size(); ++q) { if (!piCount[q]) continue; @@ -458,8 +470,9 @@ void MD5Importer::LoadMD5MeshFile() { // there are models which have weights which don't sum to 1 ... ai_real fSum = 0.0; - for (unsigned int jub = (*iter).mFirstWeight, w = jub; w < jub + (*iter).mNumWeights; ++w) + for (unsigned int jub = (*iter).mFirstWeight, w = jub; w < jub + (*iter).mNumWeights; ++w) { fSum += meshSrc.mWeights[w].mWeight; + } if (!fSum) { ASSIMP_LOG_ERROR("MD5MESH: The sum of all vertex bone weights is 0"); continue; @@ -467,11 +480,12 @@ void MD5Importer::LoadMD5MeshFile() { // process bone weights for (unsigned int jub = (*iter).mFirstWeight, w = jub; w < jub + (*iter).mNumWeights; ++w) { - if (w >= meshSrc.mWeights.size()) + if (w >= meshSrc.mWeights.size()) { throw DeadlyImportError("MD5MESH: Invalid weight index"); + } MD5::WeightDesc &weightDesc = meshSrc.mWeights[w]; - if (weightDesc.mWeight < AI_MD5_WEIGHT_EPSILON && weightDesc.mWeight >= -AI_MD5_WEIGHT_EPSILON) { + if (weightDesc.mWeight < AI_MD5_WEIGHT_EPSILON && weightDesc.mWeight >= -AI_MD5_WEIGHT_EPSILON) { continue; } @@ -510,7 +524,7 @@ void MD5Importer::LoadMD5MeshFile() { // generate a material for the mesh aiMaterial *mat = new aiMaterial(); - pScene->mMaterials[n] = mat; + mScene->mMaterials[n] = mat; // insert the typical doom3 textures: // nnn_local.tga - normal map @@ -553,13 +567,14 @@ void MD5Importer::LoadMD5AnimFile() { // Check whether we can read from the file if (!file.get() || !file->FileSize()) { - throw DeadlyImportError("Failed to open MD3 file " + pFile + "."); + ASSIMP_LOG_WARN("Failed to read MD5ANIM file: " + pFile); + return; } LoadFileIntoMemory(file.get()); // parse the basic file structure - MD5::MD5Parser parser(mBuffer, fileSize); + MD5::MD5Parser parser(mBuffer, mFileSize); // load the animation information from the parse tree MD5::MD5AnimParser animParser(parser.mSections); @@ -569,10 +584,10 @@ void MD5Importer::LoadMD5AnimFile() { animParser.mBaseFrames.size() != animParser.mAnimatedBones.size()) { ASSIMP_LOG_ERROR("MD5ANIM: No frames or animated bones loaded"); } else { - bHadMD5Anim = true; + mHadMD5Anim = true; - pScene->mAnimations = new aiAnimation *[pScene->mNumAnimations = 1]; - aiAnimation *anim = pScene->mAnimations[0] = new aiAnimation(); + mScene->mAnimations = new aiAnimation *[mScene->mNumAnimations = 1]; + aiAnimation *anim = mScene->mAnimations[0] = new aiAnimation(); anim->mNumChannels = (unsigned int)animParser.mAnimatedBones.size(); anim->mChannels = new aiNodeAnim *[anim->mNumChannels]; for (unsigned int i = 0; i < anim->mNumChannels; ++i) { @@ -638,15 +653,15 @@ void MD5Importer::LoadMD5AnimFile() { // If we didn't build the hierarchy yet (== we didn't load a MD5MESH), // construct it now from the data given in the MD5ANIM. - if (!pScene->mRootNode) { - pScene->mRootNode = new aiNode(); - pScene->mRootNode->mName.Set(""); + if (!mScene->mRootNode) { + mScene->mRootNode = new aiNode(); + mScene->mRootNode->mName.Set(""); - AttachChilds_Anim(-1, pScene->mRootNode, animParser.mAnimatedBones, (const aiNodeAnim **)anim->mChannels); + AttachChilds_Anim(-1, mScene->mRootNode, animParser.mAnimatedBones, (const aiNodeAnim **)anim->mChannels); // Call SkeletonMeshBuilder to construct a mesh to represent the shape - if (pScene->mRootNode->mNumChildren) { - SkeletonMeshBuilder skeleton_maker(pScene, pScene->mRootNode->mChildren[0]); + if (mScene->mRootNode->mNumChildren) { + SkeletonMeshBuilder skeleton_maker(mScene, mScene->mRootNode->mChildren[0]); } } } @@ -662,11 +677,11 @@ void MD5Importer::LoadMD5CameraFile() { if (!file.get() || !file->FileSize()) { throw DeadlyImportError("Failed to read MD5CAMERA file: " + pFile); } - bHadMD5Camera = true; + mHadMD5Camera = true; LoadFileIntoMemory(file.get()); // parse the basic file structure - MD5::MD5Parser parser(mBuffer, fileSize); + MD5::MD5Parser parser(mBuffer, mFileSize); // load the camera animation data from the parse tree MD5::MD5CameraParser cameraParser(parser.mSections); @@ -680,14 +695,14 @@ void MD5Importer::LoadMD5CameraFile() { // Construct output graph - a simple root with a dummy child. // The root node performs the coordinate system conversion - aiNode *root = pScene->mRootNode = new aiNode(""); + aiNode *root = mScene->mRootNode = new aiNode(""); root->mChildren = new aiNode *[root->mNumChildren = 1]; root->mChildren[0] = new aiNode(""); root->mChildren[0]->mParent = root; // ... but with one camera assigned to it - pScene->mCameras = new aiCamera *[pScene->mNumCameras = 1]; - aiCamera *cam = pScene->mCameras[0] = new aiCamera(); + mScene->mCameras = new aiCamera *[mScene->mNumCameras = 1]; + aiCamera *cam = mScene->mCameras[0] = new aiCamera(); cam->mName = ""; // FIXME: Fov is currently set to the first frame's value @@ -704,8 +719,8 @@ void MD5Importer::LoadMD5CameraFile() { cuts.push_back(static_cast(frames.size() - 1)); } - pScene->mNumAnimations = static_cast(cuts.size() - 1); - aiAnimation **tmp = pScene->mAnimations = new aiAnimation *[pScene->mNumAnimations]; + mScene->mNumAnimations = static_cast(cuts.size() - 1); + aiAnimation **tmp = mScene->mAnimations = new aiAnimation *[mScene->mNumAnimations]; for (std::vector::const_iterator it = cuts.begin(); it != cuts.end() - 1; ++it) { aiAnimation *anim = *tmp++ = new aiAnimation(); diff --git a/code/AssetLib/MD5/MD5Loader.h b/code/AssetLib/MD5/MD5Loader.h index cfdd9ed0e..f62a57e68 100644 --- a/code/AssetLib/MD5/MD5Loader.h +++ b/code/AssetLib/MD5/MD5Loader.h @@ -4,7 +4,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2020, assimp team - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -156,25 +155,25 @@ protected: char *mBuffer; /** Size of the file */ - unsigned int fileSize; + unsigned int mFileSize; /** Current line number. For debugging purposes */ - unsigned int iLineNumber; + unsigned int mLineNumber; /** Scene to be filled */ - aiScene *pScene; + aiScene *mScene; /** true if a MD5MESH file has already been parsed */ - bool bHadMD5Mesh; + bool mHadMD5Mesh; /** true if a MD5ANIM file has already been parsed */ - bool bHadMD5Anim; + bool mHadMD5Anim; /** true if a MD5CAMERA file has already been parsed */ - bool bHadMD5Camera; + bool mHadMD5Camera; /** configuration option: prevent anim autoload */ - bool configNoAutoLoad; + bool mCconfigNoAutoLoad; }; } // end of namespace Assimp From f6b4370f6ac1bf2db0ef9edeb0ff1ce8c7e61aab Mon Sep 17 00:00:00 2001 From: Evangel Date: Fri, 26 Jun 2020 14:26:45 +1000 Subject: [PATCH 47/62] Added arbitrary recursive metadata to allow for glTF2's extensions to be properly represented. Primary changes are to include/assimp/metadata.h, adding in the aiMetadata GetAiType function, adding the operator= to allow an aiMetadata type to be assigned, adding a check for the AI_AIMETADATA type flag as it can't be trivially memcpy'd. operator= is implemented with a by-value argument as then the copy is made by the copy constructor and we can just swap everything out and let the destructor handle the mess. Implemented parsing of the "extensions" flag on all glTF2 Nodes. Doesn't use the ReadValue helper function on numbers as it did not seem to fill out the Nullable structure properly. --- code/AssetLib/glTF2/glTF2Asset.h | 44 +++++++++++++++++++++++++++ code/AssetLib/glTF2/glTF2Asset.inl | 39 ++++++++++++++++++++++++ code/AssetLib/glTF2/glTF2Importer.cpp | 32 +++++++++++++++++-- include/assimp/metadata.h | 30 ++++++++++++++++-- 4 files changed, 140 insertions(+), 5 deletions(-) diff --git a/code/AssetLib/glTF2/glTF2Asset.h b/code/AssetLib/glTF2/glTF2Asset.h index ffecd3dbf..543bef95c 100644 --- a/code/AssetLib/glTF2/glTF2Asset.h +++ b/code/AssetLib/glTF2/glTF2Asset.h @@ -784,6 +784,48 @@ struct Mesh : public Object { void Read(Value &pJSON_Object, Asset &pAsset_Root); }; +struct CustomExtension : public Object { + // + // A struct containing custom extension data added to a glTF2 file + // Has to contain Object, Array, String, Double, Uint64, and Int64 at a minimum + // String, Double, Uint64, and Int64 are stored in the Nullables + // Object and Array are stored in the std::vector + // + + Nullable mStringValue; + Nullable mDoubleValue; + Nullable mUint64Value; + Nullable mInt64Value; + + // std::vector handles both Object and Array + Nullable> mValues; + + operator bool() const { + return Size(); + } + + size_t Size() const { + if (mValues.isPresent) { + return mValues.value.size(); + } else if (mStringValue.isPresent || mDoubleValue.isPresent || mUint64Value.isPresent || mInt64Value.isPresent) { + return 1; + } + return 0; + } + + CustomExtension() = default; + + CustomExtension(const CustomExtension& other) + : Object(other) + , mStringValue(other.mStringValue) + , mDoubleValue(other.mDoubleValue) + , mUint64Value(other.mUint64Value) + , mInt64Value(other.mInt64Value) + , mValues(other.mValues) + { + } +}; + struct Node : public Object { std::vector> children; std::vector> meshes; @@ -802,6 +844,8 @@ struct Node : public Object { Ref parent; //!< This is not part of the glTF specification. Used as a helper. + CustomExtension extensions; + Node() {} void Read(Value &obj, Asset &r); }; diff --git a/code/AssetLib/glTF2/glTF2Asset.inl b/code/AssetLib/glTF2/glTF2Asset.inl index 5a99525b2..71b164149 100644 --- a/code/AssetLib/glTF2/glTF2Asset.inl +++ b/code/AssetLib/glTF2/glTF2Asset.inl @@ -1207,6 +1207,43 @@ inline void Light::Read(Value &obj, Asset & /*r*/) { } } +inline CustomExtension ReadExtensions(const char *name, Value& obj) { + CustomExtension ret; + ret.name = name; + if (obj.IsObject()) { + ret.mValues.isPresent = true; + for (auto it = obj.MemberBegin(); it != obj.MemberEnd(); ++it) { + auto& val = it->value; + ret.mValues.value.push_back(ReadExtensions(it->name.GetString(), val)); + } + } + else if (obj.IsArray()) { + ret.mValues.value.reserve(obj.Size()); + ret.mValues.isPresent = true; + for (unsigned int i = 0; i < obj.Size(); ++i) + { + ret.mValues.value.push_back(ReadExtensions(name, obj[i])); + } + } + else if (obj.IsNumber()) { + if (obj.IsUint64()) { + ret.mUint64Value.value = obj.GetUint64(); + ret.mUint64Value.isPresent = true; + } else if (obj.IsInt64()) { + ret.mInt64Value.value = obj.GetInt64(); + ret.mInt64Value.isPresent = true; + } else if (obj.IsDouble()) { + ret.mDoubleValue.value = obj.GetDouble(); + ret.mDoubleValue.isPresent = true; + } + } + else if (obj.IsString()) { + ReadValue(obj, ret.mStringValue); + ret.mStringValue.isPresent = true; + } + return ret; +} + inline void Node::Read(Value &obj, Asset &r) { if (name.empty()) { name = id; @@ -1261,6 +1298,8 @@ inline void Node::Read(Value &obj, Asset &r) { Value *curExtensions = FindObject(obj, "extensions"); if (nullptr != curExtensions) { + this->extensions = ReadExtensions("extensions", *curExtensions); + if (r.extensionsUsed.KHR_lights_punctual) { if (Value *ext = FindObject(*curExtensions, "KHR_lights_punctual")) { Value *curLight = FindUInt(*ext, "light"); diff --git a/code/AssetLib/glTF2/glTF2Importer.cpp b/code/AssetLib/glTF2/glTF2Importer.cpp index 1c044e7ce..3a3c66e15 100644 --- a/code/AssetLib/glTF2/glTF2Importer.cpp +++ b/code/AssetLib/glTF2/glTF2Importer.cpp @@ -847,6 +847,24 @@ static std::string GetNodeName(const Node &node) { return node.name.empty() ? node.id : node.name; } +void ParseExtensions(aiMetadata *metadata, const CustomExtension &extension, unsigned int depth = 0) { + if (extension.mStringValue.isPresent) { + metadata->Add(extension.name.c_str(), aiString(extension.mStringValue.value)); + } else if (extension.mDoubleValue.isPresent) { + metadata->Add(extension.name.c_str(), extension.mDoubleValue.value); + } else if (extension.mUint64Value.isPresent) { + metadata->Add(extension.name.c_str(), extension.mUint64Value.value); + } else if (extension.mInt64Value.isPresent) { + metadata->Add(extension.name.c_str(), static_cast(extension.mInt64Value.value)); + } else if (extension.mValues.isPresent) { + aiMetadata val; + for (size_t i = 0; i < extension.mValues.value.size(); ++i) { + ParseExtensions(&val, extension.mValues.value[i], depth + 2); + } + metadata->Add(extension.name.c_str(), val); + } +} + aiNode *ImportNode(aiScene *pScene, glTF2::Asset &r, std::vector &meshOffsets, glTF2::Ref &ptr) { Node &node = *ptr; @@ -863,6 +881,11 @@ aiNode *ImportNode(aiScene *pScene, glTF2::Asset &r, std::vector & } } + if (node.extensions) { + ainode->mMetaData = new aiMetadata; + ParseExtensions(ainode->mMetaData, node.extensions); + } + GetNodeTransform(ainode->mTransformation, node); if (!node.meshes.empty()) { @@ -957,8 +980,13 @@ aiNode *ImportNode(aiScene *pScene, glTF2::Asset &r, std::vector & //range is optional - see https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_lights_punctual //it is added to meta data of parent node, because there is no other place to put it if (node.light->range.isPresent) { - ainode->mMetaData = aiMetadata::Alloc(1); - ainode->mMetaData->Set(0, "PBR_LightRange", node.light->range.value); + if (!ainode->mMetaData) { + ainode->mMetaData = aiMetadata::Alloc(1); + ainode->mMetaData->Set(0, "PBR_LightRange", node.light->range.value); + } + else { + ainode->mMetaData->Add("PBR_LightRange", node.light->range.value); + } } } diff --git a/include/assimp/metadata.h b/include/assimp/metadata.h index 684508a71..95d919584 100644 --- a/include/assimp/metadata.h +++ b/include/assimp/metadata.h @@ -69,7 +69,8 @@ typedef enum aiMetadataType { AI_DOUBLE = 4, AI_AISTRING = 5, AI_AIVECTOR3D = 6, - AI_META_MAX = 7, + AI_AIMETADATA = 7, + AI_META_MAX = 8, #ifndef SWIG FORCE_32BIT = INT_MAX @@ -100,6 +101,8 @@ struct aiMetadataEntry { #include +struct aiMetadata; + // ------------------------------------------------------------------------------- /** * Helper functions to get the aiType enum entry for a type @@ -127,6 +130,9 @@ inline aiMetadataType GetAiType(const aiString &) { inline aiMetadataType GetAiType(const aiVector3D &) { return AI_AIVECTOR3D; } +inline aiMetadataType GetAiType(const aiMetadata &) { + return AI_AIMETADATA; +} #endif // __cplusplus @@ -204,6 +210,11 @@ struct aiMetadata { rhs.Get(mKeys[i], v); mValues[i].mData = new aiVector3D(v); } break; + case AI_AIMETADATA: { + aiMetadata v; + rhs.Get(mKeys[i], v); + mValues[i].mData = new aiMetadata(v); + } break; #ifndef SWIG case FORCE_32BIT: #endif @@ -213,7 +224,15 @@ struct aiMetadata { } } - /** + aiMetadata &operator=(aiMetadata rhs) { + using std::swap; + swap(mNumProperties, rhs.mNumProperties); + swap(mKeys, rhs.mKeys); + swap(mValues, rhs.mValues); + return *this; + } + + /** * @brief The destructor. */ ~aiMetadata() { @@ -245,6 +264,9 @@ struct aiMetadata { case AI_AIVECTOR3D: delete static_cast(data); break; + case AI_AIMETADATA: + delete static_cast(data); + break; #ifndef SWIG case FORCE_32BIT: #endif @@ -323,8 +345,10 @@ struct aiMetadata { mValues[index].mType = GetAiType(value); // Copy the given value to the dynamic storage - if (nullptr != mValues[index].mData) { + if (nullptr != mValues[index].mData && AI_AIMETADATA != mValues[index].mType) { ::memcpy(mValues[index].mData, &value, sizeof(T)); + } else if (nullptr != mValues[index].mData && AI_AIMETADATA == mValues[index].mType) { + *static_cast(mValues[index].mData) = value; } else { mValues[index].mData = new T(value); } From d75d59a4fde93d070364cd3e7035eebc5428abf1 Mon Sep 17 00:00:00 2001 From: Evangel Date: Fri, 26 Jun 2020 15:07:42 +1000 Subject: [PATCH 48/62] Added operator== and operator!= to aiMetadata to allow for testing. Updated utMetadata.copy_test to reflect that there's now 8 metadata types. --- include/assimp/metadata.h | 83 +++++++++++++++++++++++++++++++++++++++ test/unit/utMetadata.cpp | 11 +++++- 2 files changed, 93 insertions(+), 1 deletion(-) diff --git a/include/assimp/metadata.h b/include/assimp/metadata.h index 95d919584..52121fbf1 100644 --- a/include/assimp/metadata.h +++ b/include/assimp/metadata.h @@ -442,6 +442,89 @@ struct aiMetadata { return false; } + friend bool CompareKeys(const aiMetadata &lhs, const aiMetadata &rhs) { + if (lhs.mNumProperties != rhs.mNumProperties) { + return false; + } + + for (unsigned int i = 0; i < lhs.mNumProperties; ++i) { + if (lhs.mKeys[i] != rhs.mKeys[i]) { + return false; + } + } + return true; + } + + friend bool CompareValues(const aiMetadata &lhs, const aiMetadata &rhs) { + if (lhs.mNumProperties != rhs.mNumProperties) { + return false; + } + + for (unsigned int i = 0; i < lhs.mNumProperties; ++i) { + if (lhs.mValues[i].mType != rhs.mValues[i].mType) { + return false; + } + + switch (lhs.mValues[i].mType) { + case AI_BOOL: { + if (*static_cast(lhs.mValues[i].mData) != *static_cast(rhs.mValues[i].mData)) { + return false; + } + } break; + case AI_INT32: { + if (*static_cast(lhs.mValues[i].mData) != *static_cast(rhs.mValues[i].mData)) { + return false; + } + } break; + case AI_UINT64: { + if (*static_cast(lhs.mValues[i].mData) != *static_cast(rhs.mValues[i].mData)) { + return false; + } + } break; + case AI_FLOAT: { + if (*static_cast(lhs.mValues[i].mData) != *static_cast(rhs.mValues[i].mData)) { + return false; + } + } break; + case AI_DOUBLE: { + if (*static_cast(lhs.mValues[i].mData) != *static_cast(rhs.mValues[i].mData)) { + return false; + } + } break; + case AI_AISTRING: { + if (*static_cast(lhs.mValues[i].mData) != *static_cast(rhs.mValues[i].mData)) { + return false; + } + } break; + case AI_AIVECTOR3D: { + if (*static_cast(lhs.mValues[i].mData) != *static_cast(rhs.mValues[i].mData)) { + return false; + } + } break; + case AI_AIMETADATA: { + if (*static_cast(lhs.mValues[i].mData) != *static_cast(rhs.mValues[i].mData)) { + return false; + } + } break; +#ifndef SWIG + case FORCE_32BIT: +#endif + default: + break; + } + } + + return true; + } + + friend bool operator==(const aiMetadata &lhs, const aiMetadata &rhs) { + return CompareKeys(lhs, rhs) && CompareValues(lhs, rhs); + } + + friend bool operator!=(const aiMetadata &lhs, const aiMetadata &rhs) { + return !(lhs == rhs); + } + #endif // __cplusplus }; diff --git a/test/unit/utMetadata.cpp b/test/unit/utMetadata.cpp index a605107db..81ab61435 100644 --- a/test/unit/utMetadata.cpp +++ b/test/unit/utMetadata.cpp @@ -197,9 +197,11 @@ TEST_F( utMetadata, copy_test ) { m_data->Set( 5, "aiString", strVal ); aiVector3D vecVal( 1, 2, 3 ); m_data->Set( 6, "aiVector3D", vecVal ); + aiMetadata metaVal; + m_data->Set( 7, "aiMetadata", metaVal ); aiMetadata copy( *m_data ); - EXPECT_EQ( 7u, copy.mNumProperties ); + EXPECT_EQ( 8u, copy.mNumProperties ); // bool test { @@ -251,4 +253,11 @@ TEST_F( utMetadata, copy_test ) { EXPECT_TRUE( copy.Get( "aiVector3D", v ) ); EXPECT_EQ( vecVal, v ); } + + // metadata test + { + aiMetadata v; + EXPECT_TRUE( copy.Get( "aiMetadata", v ) ); + EXPECT_EQ( metaVal, v ); + } } From 6d85280c8dcd936a19caedf07eb9d454e3e511a8 Mon Sep 17 00:00:00 2001 From: Evangel Date: Sat, 27 Jun 2020 12:53:26 +1000 Subject: [PATCH 49/62] Added bool, removed unused debug parameter --- code/AssetLib/glTF2/glTF2Asset.h | 4 +++- code/AssetLib/glTF2/glTF2Asset.inl | 4 ++++ code/AssetLib/glTF2/glTF2Importer.cpp | 6 ++++-- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/code/AssetLib/glTF2/glTF2Asset.h b/code/AssetLib/glTF2/glTF2Asset.h index 543bef95c..f79ddee87 100644 --- a/code/AssetLib/glTF2/glTF2Asset.h +++ b/code/AssetLib/glTF2/glTF2Asset.h @@ -796,6 +796,7 @@ struct CustomExtension : public Object { Nullable mDoubleValue; Nullable mUint64Value; Nullable mInt64Value; + Nullable mBoolValue; // std::vector handles both Object and Array Nullable> mValues; @@ -807,7 +808,7 @@ struct CustomExtension : public Object { size_t Size() const { if (mValues.isPresent) { return mValues.value.size(); - } else if (mStringValue.isPresent || mDoubleValue.isPresent || mUint64Value.isPresent || mInt64Value.isPresent) { + } else if (mStringValue.isPresent || mDoubleValue.isPresent || mUint64Value.isPresent || mInt64Value.isPresent || mBoolValue.isPresent) { return 1; } return 0; @@ -821,6 +822,7 @@ struct CustomExtension : public Object { , mDoubleValue(other.mDoubleValue) , mUint64Value(other.mUint64Value) , mInt64Value(other.mInt64Value) + , mBoolValue(other.mBoolValue) , mValues(other.mValues) { } diff --git a/code/AssetLib/glTF2/glTF2Asset.inl b/code/AssetLib/glTF2/glTF2Asset.inl index 71b164149..94f8d9ffa 100644 --- a/code/AssetLib/glTF2/glTF2Asset.inl +++ b/code/AssetLib/glTF2/glTF2Asset.inl @@ -1241,6 +1241,10 @@ inline CustomExtension ReadExtensions(const char *name, Value& obj) { ReadValue(obj, ret.mStringValue); ret.mStringValue.isPresent = true; } + else if (obj.IsBool()) { + ret.mBoolValue.value = obj.GetBool(); + ret.mBoolValue.isPresent = true; + } return ret; } diff --git a/code/AssetLib/glTF2/glTF2Importer.cpp b/code/AssetLib/glTF2/glTF2Importer.cpp index 3a3c66e15..4d740d8c1 100644 --- a/code/AssetLib/glTF2/glTF2Importer.cpp +++ b/code/AssetLib/glTF2/glTF2Importer.cpp @@ -847,7 +847,7 @@ static std::string GetNodeName(const Node &node) { return node.name.empty() ? node.id : node.name; } -void ParseExtensions(aiMetadata *metadata, const CustomExtension &extension, unsigned int depth = 0) { +void ParseExtensions(aiMetadata *metadata, const CustomExtension &extension) { if (extension.mStringValue.isPresent) { metadata->Add(extension.name.c_str(), aiString(extension.mStringValue.value)); } else if (extension.mDoubleValue.isPresent) { @@ -856,10 +856,12 @@ void ParseExtensions(aiMetadata *metadata, const CustomExtension &extension, uns metadata->Add(extension.name.c_str(), extension.mUint64Value.value); } else if (extension.mInt64Value.isPresent) { metadata->Add(extension.name.c_str(), static_cast(extension.mInt64Value.value)); + } else if (extension.mBoolValue.isPresent) { + metadata->Add(extension.name.c_str(), extension.mBoolValue.value); } else if (extension.mValues.isPresent) { aiMetadata val; for (size_t i = 0; i < extension.mValues.value.size(); ++i) { - ParseExtensions(&val, extension.mValues.value[i], depth + 2); + ParseExtensions(&val, extension.mValues.value[i]); } metadata->Add(extension.name.c_str(), val); } From b2f05a9a54d61d5d38790efec6c118a89ac04b68 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 28 Jun 2020 19:18:36 +0200 Subject: [PATCH 50/62] rename fuzzer target --- fuzz/{assimp_fuzzer.cpp => assimp_fuzzer.cc} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename fuzz/{assimp_fuzzer.cpp => assimp_fuzzer.cc} (100%) diff --git a/fuzz/assimp_fuzzer.cpp b/fuzz/assimp_fuzzer.cc similarity index 100% rename from fuzz/assimp_fuzzer.cpp rename to fuzz/assimp_fuzzer.cc From 0b18d27042b37429a3f82fd546500411fe1360c2 Mon Sep 17 00:00:00 2001 From: Hill Ma Date: Sun, 28 Jun 2020 15:58:20 -0700 Subject: [PATCH 51/62] Use strrchr() when finding the '.' that begins the file extension. Sometimes we encounter file paths like ../foo/bar.obj; searching from the end of the string would yield the correct result. --- samples/SimpleOpenGL/Sample_SimpleOpenGL.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/SimpleOpenGL/Sample_SimpleOpenGL.c b/samples/SimpleOpenGL/Sample_SimpleOpenGL.c index bcc964efe..01704a1e4 100644 --- a/samples/SimpleOpenGL/Sample_SimpleOpenGL.c +++ b/samples/SimpleOpenGL/Sample_SimpleOpenGL.c @@ -376,7 +376,7 @@ int main(int argc, char **argv) // Check and validate the specified model file extension. model_file = argv[1]; - const char* extension = strchr(model_file, '.'); + const char* extension = strrchr(model_file, '.'); if (!extension) { print_error("Please provide a file with a valid extension."); return EXIT_FAILURE; From 30f09e9fc019a078228ea818ba7dc1a41b436a3c Mon Sep 17 00:00:00 2001 From: Hill Ma Date: Sun, 28 Jun 2020 17:36:21 -0700 Subject: [PATCH 52/62] Fix build when ASSIMP_DOUBLE_PRECISION is on. Tested: $ cmake -DASSIMP_DOUBLE_PRECISION=1 -DASSIMP_BUILD_MDL_IMPORTER=0 ..; make The MDL importer is disabled due to the fact that there is some float-only code in MDL. This also means bin/assimp and bin/unit would not link successfully with the above build flags. --- code/Common/Assimp.cpp | 2 +- code/Common/SpatialSort.cpp | 2 +- code/PostProcessing/ProcessHelper.h | 2 +- include/assimp/cimport.h | 2 +- test/unit/AssimpAPITest_aiMatrix4x4.cpp | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/code/Common/Assimp.cpp b/code/Common/Assimp.cpp index 33de72e0f..26aa52300 100644 --- a/code/Common/Assimp.cpp +++ b/code/Common/Assimp.cpp @@ -1079,7 +1079,7 @@ ASSIMP_API void aiMatrix4DecomposeIntoScalingAxisAnglePosition( const C_STRUCT aiMatrix4x4 *mat, C_STRUCT aiVector3D *scaling, C_STRUCT aiVector3D *axis, - float *angle, + ai_real *angle, C_STRUCT aiVector3D *position) { ai_assert(nullptr != mat); ai_assert(nullptr != scaling); diff --git a/code/Common/SpatialSort.cpp b/code/Common/SpatialSort.cpp index 86e22b242..3b8a64606 100644 --- a/code/Common/SpatialSort.cpp +++ b/code/Common/SpatialSort.cpp @@ -214,7 +214,7 @@ BinFloat ToBinary(const ai_real &pValue) { const bool OneComplement = ((-42 == ~42) && (binValue & 0x80000000)); if (DefaultValue) - return BinFloat(1 << (CHAR_BIT * sizeof(BinFloat) - 1)) - binValue; + return BinFloat(BinFloat(1) << (CHAR_BIT * sizeof(BinFloat) - 1)) - binValue; // One's complement? else if (OneComplement) return BinFloat(-0) - binValue; diff --git a/code/PostProcessing/ProcessHelper.h b/code/PostProcessing/ProcessHelper.h index 660555ef0..8520b21ec 100644 --- a/code/PostProcessing/ProcessHelper.h +++ b/code/PostProcessing/ProcessHelper.h @@ -222,7 +222,7 @@ template <> struct MinMaxChooser { void operator()(aiVertexWeight &min, aiVertexWeight &max) { MinMaxChooser()(min.mVertexId, max.mVertexId); - MinMaxChooser()(min.mWeight, max.mWeight); + MinMaxChooser()(min.mWeight, max.mWeight); } }; diff --git a/include/assimp/cimport.h b/include/assimp/cimport.h index a6ab93051..3e1b75a31 100644 --- a/include/assimp/cimport.h +++ b/include/assimp/cimport.h @@ -1044,7 +1044,7 @@ ASSIMP_API void aiMatrix4DecomposeIntoScalingAxisAnglePosition( const C_STRUCT aiMatrix4x4* mat, C_STRUCT aiVector3D* scaling, C_STRUCT aiVector3D* axis, - float* angle, + ai_real* angle, C_STRUCT aiVector3D* position); // -------------------------------------------------------------------------------- diff --git a/test/unit/AssimpAPITest_aiMatrix4x4.cpp b/test/unit/AssimpAPITest_aiMatrix4x4.cpp index 2c89726e0..89883dc0d 100644 --- a/test/unit/AssimpAPITest_aiMatrix4x4.cpp +++ b/test/unit/AssimpAPITest_aiMatrix4x4.cpp @@ -176,7 +176,7 @@ TEST_F(AssimpAPITest_aiMatrix4x4, aiMatrix4DecomposeIntoScalingAxisAnglePosition aiVector3D scaling_c, scaling_cpp, axis_c, axis_cpp, position_c, position_cpp; - float angle_c, angle_cpp; + ai_real angle_c, angle_cpp; result_c = result_cpp = get_predetermined_transformation_matrix_for_decomposition(); result_cpp.Decompose(scaling_cpp, axis_cpp, angle_cpp, position_cpp); From ba94bfd1975c3b2bedf04d8c078a4a8160c90208 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 29 Jun 2020 09:51:00 +0200 Subject: [PATCH 53/62] Move patreon to contribution --- Readme.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Readme.md b/Readme.md index 15e76b9d2..66b0a31df 100644 --- a/Readme.md +++ b/Readme.md @@ -25,16 +25,6 @@ Additionally, assimp features various __mesh post processing tools__: normals an This is the development repo containing the latest features and bugfixes. For productive use though, we recommend one of the stable releases available from [Github Assimp Releases](https://github.com/assimp/assimp/releases). -Monthly donations via Patreon: -
[![Patreon](https://cloud.githubusercontent.com/assets/8225057/5990484/70413560-a9ab-11e4-8942-1a63607c0b00.png)](http://www.patreon.com/assimp) - -
- -One-off donations via PayPal: -
[![PayPal](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=4JRJVPXC4QJM4) - -
- Please check our Wiki as well: https://github.com/assimp/assimp/wiki If you want to check our Model-Database, use the following repo: https://github.com/assimp/assimp-mdb @@ -196,6 +186,16 @@ Become a financial contributor and help us sustain our community. [[Contribute]( +Monthly donations via Patreon: +
[![Patreon](https://cloud.githubusercontent.com/assets/8225057/5990484/70413560-a9ab-11e4-8942-1a63607c0b00.png)](http://www.patreon.com/assimp) + +
+ +One-off donations via PayPal: +
[![PayPal](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=4JRJVPXC4QJM4) + +
+ #### Organizations Support this project with your organization. Your logo will show up here with a link to your website. [[Contribute](https://opencollective.com/assimp/contribute)] From 28b65c84b0ca2dcd2e6c38d3fac209c3890f9207 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 29 Jun 2020 09:52:36 +0200 Subject: [PATCH 54/62] Create fileformats.md Optimize the readabilaty of the frontpage. --- doc/Fileformats.md | 87 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 doc/Fileformats.md diff --git a/doc/Fileformats.md b/doc/Fileformats.md new file mode 100644 index 000000000..c9116e2e7 --- /dev/null +++ b/doc/Fileformats.md @@ -0,0 +1,87 @@ +#### Supported file formats #### + +__Importers__: + +- 3D +- [3DS](https://en.wikipedia.org/wiki/.3ds) +- [3MF](https://en.wikipedia.org/wiki/3D_Manufacturing_Format) +- AC +- [AC3D](https://en.wikipedia.org/wiki/AC3D) +- ACC +- AMJ +- ASE +- ASK +- B3D +- [BLEND](https://en.wikipedia.org/wiki/.blend_(file_format)) +- [BVH](https://en.wikipedia.org/wiki/Biovision_Hierarchy) +- CMS +- COB +- [DAE/Collada](https://en.wikipedia.org/wiki/COLLADA) +- [DXF](https://en.wikipedia.org/wiki/AutoCAD_DXF) +- ENFF +- [FBX](https://en.wikipedia.org/wiki/FBX) +- [glTF 1.0](https://en.wikipedia.org/wiki/GlTF#glTF_1.0) + GLB +- [glTF 2.0](https://en.wikipedia.org/wiki/GlTF#glTF_2.0): + At the moment for glTF2.0 the following extensions are supported: + + KHR_lights_punctual ( 5.0 ) + + KHR_materials_pbrSpecularGlossiness ( 5.0 ) + + KHR_materials_unlit ( 5.0 ) + + KHR_texture_transform ( 5.1 under test ) +- HMB +- IFC-STEP +- IRR / IRRMESH +- [LWO](https://en.wikipedia.org/wiki/LightWave_3D) +- LWS +- LXO +- [M3D](https://bztsrc.gitlab.io/model3d) +- MD2 +- MD3 +- MD5 +- MDC +- MDL +- MESH / MESH.XML +- MOT +- MS3D +- NDO +- NFF +- [OBJ](https://en.wikipedia.org/wiki/Wavefront_.obj_file) +- [OFF](https://en.wikipedia.org/wiki/OFF_(file_format)) +- [OGEX](https://en.wikipedia.org/wiki/Open_Game_Engine_Exchange) +- [PLY](https://en.wikipedia.org/wiki/PLY_(file_format)) +- PMX +- PRJ +- Q3O +- Q3S +- RAW +- SCN +- SIB +- SMD +- [STP](https://en.wikipedia.org/wiki/ISO_10303-21) +- [STL](https://en.wikipedia.org/wiki/STL_(file_format)) +- TER +- UC +- VTA +- X +- [X3D](https://en.wikipedia.org/wiki/X3D) +- XGL +- ZGL + +Additionally, some formats are supported by dependency on non-free code or external SDKs (not built by default): + +- [C4D](https://en.wikipedia.org/wiki/Cinema_4D) (https://github.com/assimp/assimp/wiki/Cinema4D-&-Melange) IMporting geometry + node hierarchy are currently supported + +__Exporters__: + +- DAE (Collada) +- STL +- OBJ +- PLY +- X +- 3DS +- JSON (for WebGl, via https://github.com/acgessler/assimp2json) +- ASSBIN +- STEP +- glTF 1.0 (partial) +- glTF 2.0 (partial) +- 3MF ( experimental ) +- FBX ( experimental ) From 9a873388545788e4fbd891cff424fd63675b5aa9 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 29 Jun 2020 09:55:29 +0200 Subject: [PATCH 55/62] Update Readme.md --- Readme.md | 87 +------------------------------------------------------ 1 file changed, 1 insertion(+), 86 deletions(-) diff --git a/Readme.md b/Readme.md index 66b0a31df..dc54870a0 100644 --- a/Readme.md +++ b/Readme.md @@ -30,92 +30,7 @@ Please check our Wiki as well: https://github.com/assimp/assimp/wiki If you want to check our Model-Database, use the following repo: https://github.com/assimp/assimp-mdb #### Supported file formats #### - -__Importers__: - -- 3D -- [3DS](https://en.wikipedia.org/wiki/.3ds) -- [3MF](https://en.wikipedia.org/wiki/3D_Manufacturing_Format) -- AC -- [AC3D](https://en.wikipedia.org/wiki/AC3D) -- ACC -- AMJ -- ASE -- ASK -- B3D -- [BLEND](https://en.wikipedia.org/wiki/.blend_(file_format)) -- [BVH](https://en.wikipedia.org/wiki/Biovision_Hierarchy) -- CMS -- COB -- [DAE/Collada](https://en.wikipedia.org/wiki/COLLADA) -- [DXF](https://en.wikipedia.org/wiki/AutoCAD_DXF) -- ENFF -- [FBX](https://en.wikipedia.org/wiki/FBX) -- [glTF 1.0](https://en.wikipedia.org/wiki/GlTF#glTF_1.0) + GLB -- [glTF 2.0](https://en.wikipedia.org/wiki/GlTF#glTF_2.0): - At the moment for glTF2.0 the following extensions are supported: - + KHR_lights_punctual ( 5.0 ) - + KHR_materials_pbrSpecularGlossiness ( 5.0 ) - + KHR_materials_unlit ( 5.0 ) - + KHR_texture_transform ( 5.1 under test ) -- HMB -- IFC-STEP -- IRR / IRRMESH -- [LWO](https://en.wikipedia.org/wiki/LightWave_3D) -- LWS -- LXO -- [M3D](https://bztsrc.gitlab.io/model3d) -- MD2 -- MD3 -- MD5 -- MDC -- MDL -- MESH / MESH.XML -- MOT -- MS3D -- NDO -- NFF -- [OBJ](https://en.wikipedia.org/wiki/Wavefront_.obj_file) -- [OFF](https://en.wikipedia.org/wiki/OFF_(file_format)) -- [OGEX](https://en.wikipedia.org/wiki/Open_Game_Engine_Exchange) -- [PLY](https://en.wikipedia.org/wiki/PLY_(file_format)) -- PMX -- PRJ -- Q3O -- Q3S -- RAW -- SCN -- SIB -- SMD -- [STP](https://en.wikipedia.org/wiki/ISO_10303-21) -- [STL](https://en.wikipedia.org/wiki/STL_(file_format)) -- TER -- UC -- VTA -- X -- [X3D](https://en.wikipedia.org/wiki/X3D) -- XGL -- ZGL - -Additionally, some formats are supported by dependency on non-free code or external SDKs (not built by default): - -- [C4D](https://en.wikipedia.org/wiki/Cinema_4D) (https://github.com/assimp/assimp/wiki/Cinema4D-&-Melange) IMporting geometry + node hierarchy are currently supported - -__Exporters__: - -- DAE (Collada) -- STL -- OBJ -- PLY -- X -- 3DS -- JSON (for WebGl, via https://github.com/acgessler/assimp2json) -- ASSBIN -- STEP -- glTF 1.0 (partial) -- glTF 2.0 (partial) -- 3MF ( experimental ) -- FBX ( experimental ) +You can find the complete list of supported file-formats [here](https://github.com/assimp/assimp/blob/master/doc/Fileformats.md) ### Building ### Take a look into the https://github.com/assimp/assimp/blob/master/Build.md file. We are available in vcpkg, and our build system is CMake; if you used CMake before there is a good chance you know what to do. From 03340787ecf769837fabc2b7ba9adfa6a46f4f66 Mon Sep 17 00:00:00 2001 From: Marc-Antoine Lortie Date: Mon, 29 Jun 2020 07:50:51 -0400 Subject: [PATCH 56/62] Fixed variable in loop - HL1MDLLoader.cpp Commit 7e5a0acc48efc54d7aa7900c36cd63db1fbeec9b made changes to HL1MDLLoader.cpp. Several variables have been renamed. A loop variable 'i' was renamed to faceIdx, but one reference was left unchanged. --- code/AssetLib/MDL/HalfLife/HL1MDLLoader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/AssetLib/MDL/HalfLife/HL1MDLLoader.cpp b/code/AssetLib/MDL/HalfLife/HL1MDLLoader.cpp index 261214dac..2bb7b42ee 100644 --- a/code/AssetLib/MDL/HalfLife/HL1MDLLoader.cpp +++ b/code/AssetLib/MDL/HalfLife/HL1MDLLoader.cpp @@ -829,7 +829,7 @@ void HL1MDLLoader::read_meshes() { } } else { for (int faceIdx = 0; faceIdx < num_faces; ++faceIdx) { - if (i & 1) { + if (faceIdx & 1) { // Preserve winding order. mesh_faces.push_back(HL1MeshFace{ tricmds[faceIdx + 1], From 693da43095555a809d9d840a0ecc442ed3a3a00c Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Thu, 2 Jul 2020 15:22:06 +0200 Subject: [PATCH 57/62] closes https://github.com/assimp/assimp/issues/3305: remove merge issue. --- code/AMF/AMFImporter.cpp | 707 --------------------------------------- 1 file changed, 707 deletions(-) delete mode 100644 code/AMF/AMFImporter.cpp diff --git a/code/AMF/AMFImporter.cpp b/code/AMF/AMFImporter.cpp deleted file mode 100644 index d93ca54cf..000000000 --- a/code/AMF/AMFImporter.cpp +++ /dev/null @@ -1,707 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (assimp) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2020, assimp team - - - -All rights reserved. - -Redistribution and use of this software in source and binary forms, -with or without modification, are permitted provided that the following -conditions are met: - -* Redistributions of source code must retain the above -copyright notice, this list of conditions and the -following disclaimer. - -* Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the -following disclaimer in the documentation and/or other -materials provided with the distribution. - -* Neither the name of the assimp team, nor the names of its -contributors may be used to endorse or promote products -derived from this software without specific prior -written permission of the assimp team. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------------------- -*/ - -/// \file AMFImporter.cpp -/// \brief AMF-format files importer for Assimp: main algorithm implementation. -/// \date 2016 -/// \author smal.root@gmail.com - -#ifndef ASSIMP_BUILD_NO_AMF_IMPORTER - -// Header files, Assimp. -#include "AMFImporter.hpp" -#include "AMFImporter_Macro.hpp" - -#include -#include - -// Header files, stdlib. -#include - -namespace Assimp -{ - -/// \var aiImporterDesc AMFImporter::Description -/// Conastant which hold importer description -const aiImporterDesc AMFImporter::Description = { - "Additive manufacturing file format(AMF) Importer", - "smalcom", - "", - "See documentation in source code. Chapter: Limitations.", - aiImporterFlags_SupportTextFlavour | aiImporterFlags_LimitedSupport | aiImporterFlags_Experimental, - 0, - 0, - 0, - 0, - "amf" -}; - -void AMFImporter::Clear() -{ - mNodeElement_Cur = nullptr; - mUnit.clear(); - mMaterial_Converted.clear(); - mTexture_Converted.clear(); - // Delete all elements - if(!mNodeElement_List.empty()) - { - for(CAMFImporter_NodeElement* ne: mNodeElement_List) { delete ne; } - - mNodeElement_List.clear(); - } -} - -AMFImporter::~AMFImporter() -{ - if(mReader != nullptr) delete mReader; - // Clear() is accounting if data already is deleted. So, just check again if all data is deleted. - Clear(); -} - -/*********************************************************************************************************************************************/ -/************************************************************ Functions: find set ************************************************************/ -/*********************************************************************************************************************************************/ - -bool AMFImporter::Find_NodeElement(const std::string& pID, const CAMFImporter_NodeElement::EType pType, CAMFImporter_NodeElement** pNodeElement) const -{ - for(CAMFImporter_NodeElement* ne: mNodeElement_List) - { - if((ne->ID == pID) && (ne->Type == pType)) - { - if(pNodeElement != nullptr) *pNodeElement = ne; - - return true; - } - }// for(CAMFImporter_NodeElement* ne: mNodeElement_List) - - return false; -} - -bool AMFImporter::Find_ConvertedNode(const std::string& pID, std::list& pNodeList, aiNode** pNode) const -{ -aiString node_name(pID.c_str()); - - for(aiNode* node: pNodeList) - { - if(node->mName == node_name) - { - if(pNode != nullptr) *pNode = node; - - return true; - } - }// for(aiNode* node: pNodeList) - - return false; -} - -bool AMFImporter::Find_ConvertedMaterial(const std::string& pID, const SPP_Material** pConvertedMaterial) const -{ - for(const SPP_Material& mat: mMaterial_Converted) - { - if(mat.ID == pID) - { - if(pConvertedMaterial != nullptr) *pConvertedMaterial = &mat; - - return true; - } - }// for(const SPP_Material& mat: mMaterial_Converted) - - return false; -} - -/*********************************************************************************************************************************************/ -/************************************************************ Functions: throw set ***********************************************************/ -/*********************************************************************************************************************************************/ - -void AMFImporter::Throw_CloseNotFound(const std::string& pNode) -{ - throw DeadlyImportError("Close tag for node <" + pNode + "> not found. Seems file is corrupt."); -} - -void AMFImporter::Throw_IncorrectAttr(const std::string& pAttrName) -{ - throw DeadlyImportError("Node <" + std::string(mReader->getNodeName()) + "> has incorrect attribute \"" + pAttrName + "\"."); -} - -void AMFImporter::Throw_IncorrectAttrValue(const std::string& pAttrName) -{ - throw DeadlyImportError("Attribute \"" + pAttrName + "\" in node <" + std::string(mReader->getNodeName()) + "> has incorrect value."); -} - -void AMFImporter::Throw_MoreThanOnceDefined(const std::string& pNodeType, const std::string& pDescription) -{ - throw DeadlyImportError("\"" + pNodeType + "\" node can be used only once in " + mReader->getNodeName() + ". Description: " + pDescription); -} - -void AMFImporter::Throw_ID_NotFound(const std::string& pID) const -{ - throw DeadlyImportError("Not found node with name \"" + pID + "\"."); -} - -/*********************************************************************************************************************************************/ -/************************************************************* Functions: XML set ************************************************************/ -/*********************************************************************************************************************************************/ - -void AMFImporter::XML_CheckNode_MustHaveChildren() -{ - if(mReader->isEmptyElement()) throw DeadlyImportError(std::string("Node <") + mReader->getNodeName() + "> must have children."); -} - -void AMFImporter::XML_CheckNode_SkipUnsupported(const std::string& pParentNodeName) -{ - static const size_t Uns_Skip_Len = 3; - const char* Uns_Skip[Uns_Skip_Len] = { "composite", "edge", "normal" }; - - static bool skipped_before[Uns_Skip_Len] = { false, false, false }; - - std::string nn(mReader->getNodeName()); - bool found = false; - bool close_found = false; - size_t sk_idx; - - for(sk_idx = 0; sk_idx < Uns_Skip_Len; sk_idx++) - { - if(nn != Uns_Skip[sk_idx]) continue; - - found = true; - if(mReader->isEmptyElement()) - { - close_found = true; - - goto casu_cres; - } - - while(mReader->read()) - { - if((mReader->getNodeType() == irr::io::EXN_ELEMENT_END) && (nn == mReader->getNodeName())) - { - close_found = true; - - goto casu_cres; - } - } - }// for(sk_idx = 0; sk_idx < Uns_Skip_Len; sk_idx++) - -casu_cres: - - if(!found) throw DeadlyImportError("Unknown node \"" + nn + "\" in " + pParentNodeName + "."); - if(!close_found) Throw_CloseNotFound(nn); - - if(!skipped_before[sk_idx]) - { - skipped_before[sk_idx] = true; - ASSIMP_LOG_WARN_F("Skipping node \"", nn, "\" in ", pParentNodeName, "."); - } -} - -bool AMFImporter::XML_SearchNode(const std::string& pNodeName) -{ - while(mReader->read()) - { - if((mReader->getNodeType() == irr::io::EXN_ELEMENT) && XML_CheckNode_NameEqual(pNodeName)) return true; - } - - return false; -} - -bool AMFImporter::XML_ReadNode_GetAttrVal_AsBool(const int pAttrIdx) -{ - std::string val(mReader->getAttributeValue(pAttrIdx)); - - if((val == "false") || (val == "0")) - return false; - else if((val == "true") || (val == "1")) - return true; - else - throw DeadlyImportError("Bool attribute value can contain \"false\"/\"0\" or \"true\"/\"1\" not the \"" + val + "\""); -} - -float AMFImporter::XML_ReadNode_GetAttrVal_AsFloat(const int pAttrIdx) -{ - std::string val; - float tvalf; - - ParseHelper_FixTruncatedFloatString(mReader->getAttributeValue(pAttrIdx), val); - fast_atoreal_move(val.c_str(), tvalf, false); - - return tvalf; -} - -uint32_t AMFImporter::XML_ReadNode_GetAttrVal_AsU32(const int pAttrIdx) -{ - return strtoul10(mReader->getAttributeValue(pAttrIdx)); -} - -float AMFImporter::XML_ReadNode_GetVal_AsFloat() -{ - std::string val; - float tvalf; - - if(!mReader->read()) throw DeadlyImportError("XML_ReadNode_GetVal_AsFloat. No data, seems file is corrupt."); - if(mReader->getNodeType() != irr::io::EXN_TEXT) throw DeadlyImportError("XML_ReadNode_GetVal_AsFloat. Invalid type of XML element, seems file is corrupt."); - - ParseHelper_FixTruncatedFloatString(mReader->getNodeData(), val); - fast_atoreal_move(val.c_str(), tvalf, false); - - return tvalf; -} - -uint32_t AMFImporter::XML_ReadNode_GetVal_AsU32() -{ - if(!mReader->read()) throw DeadlyImportError("XML_ReadNode_GetVal_AsU32. No data, seems file is corrupt."); - if(mReader->getNodeType() != irr::io::EXN_TEXT) throw DeadlyImportError("XML_ReadNode_GetVal_AsU32. Invalid type of XML element, seems file is corrupt."); - - return strtoul10(mReader->getNodeData()); -} - -void AMFImporter::XML_ReadNode_GetVal_AsString(std::string& pValue) -{ - if(!mReader->read()) throw DeadlyImportError("XML_ReadNode_GetVal_AsString. No data, seems file is corrupt."); - if(mReader->getNodeType() != irr::io::EXN_TEXT) - throw DeadlyImportError("XML_ReadNode_GetVal_AsString. Invalid type of XML element, seems file is corrupt."); - - pValue = mReader->getNodeData(); -} - -/*********************************************************************************************************************************************/ -/************************************************************ Functions: parse set ***********************************************************/ -/*********************************************************************************************************************************************/ - -void AMFImporter::ParseHelper_Node_Enter(CAMFImporter_NodeElement* pNode) -{ - mNodeElement_Cur->Child.push_back(pNode);// add new element to current element child list. - mNodeElement_Cur = pNode;// switch current element to new one. -} - -void AMFImporter::ParseHelper_Node_Exit() -{ - // check if we can walk up. - if(mNodeElement_Cur != nullptr) mNodeElement_Cur = mNodeElement_Cur->Parent; -} - -void AMFImporter::ParseHelper_FixTruncatedFloatString(const char* pInStr, std::string& pOutString) -{ - size_t instr_len; - - pOutString.clear(); - instr_len = strlen(pInStr); - if(!instr_len) return; - - pOutString.reserve(instr_len * 3 / 2); - // check and correct floats in format ".x". Must be "x.y". - if(pInStr[0] == '.') pOutString.push_back('0'); - - pOutString.push_back(pInStr[0]); - for(size_t ci = 1; ci < instr_len; ci++) - { - if((pInStr[ci] == '.') && ((pInStr[ci - 1] == ' ') || (pInStr[ci - 1] == '-') || (pInStr[ci - 1] == '+') || (pInStr[ci - 1] == '\t'))) - { - pOutString.push_back('0'); - pOutString.push_back('.'); - } - else - { - pOutString.push_back(pInStr[ci]); - } - } -} - -static bool ParseHelper_Decode_Base64_IsBase64(const char pChar) -{ - return (isalnum(pChar) || (pChar == '+') || (pChar == '/')); -} - -void AMFImporter::ParseHelper_Decode_Base64(const std::string& pInputBase64, std::vector& pOutputData) const -{ - // With help from - // René Nyffenegger http://www.adp-gmbh.ch/cpp/common/base64.html - const std::string base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - - uint8_t tidx = 0; - uint8_t arr4[4], arr3[3]; - - // check input data - if(pInputBase64.size() % 4) throw DeadlyImportError("Base64-encoded data must have size multiply of four."); - // prepare output place - pOutputData.clear(); - pOutputData.reserve(pInputBase64.size() / 4 * 3); - - for(size_t in_len = pInputBase64.size(), in_idx = 0; (in_len > 0) && (pInputBase64[in_idx] != '='); in_len--) - { - if(ParseHelper_Decode_Base64_IsBase64(pInputBase64[in_idx])) - { - arr4[tidx++] = pInputBase64[in_idx++]; - if(tidx == 4) - { - for(tidx = 0; tidx < 4; tidx++) arr4[tidx] = (uint8_t)base64_chars.find(arr4[tidx]); - - arr3[0] = (arr4[0] << 2) + ((arr4[1] & 0x30) >> 4); - arr3[1] = ((arr4[1] & 0x0F) << 4) + ((arr4[2] & 0x3C) >> 2); - arr3[2] = ((arr4[2] & 0x03) << 6) + arr4[3]; - for(tidx = 0; tidx < 3; tidx++) pOutputData.push_back(arr3[tidx]); - - tidx = 0; - }// if(tidx == 4) - }// if(ParseHelper_Decode_Base64_IsBase64(pInputBase64[in_idx])) - else - { - in_idx++; - }// if(ParseHelper_Decode_Base64_IsBase64(pInputBase64[in_idx])) else - } - - if(tidx) - { - for(uint8_t i = tidx; i < 4; i++) arr4[i] = 0; - for(uint8_t i = 0; i < 4; i++) arr4[i] = (uint8_t)(base64_chars.find(arr4[i])); - - arr3[0] = (arr4[0] << 2) + ((arr4[1] & 0x30) >> 4); - arr3[1] = ((arr4[1] & 0x0F) << 4) + ((arr4[2] & 0x3C) >> 2); - arr3[2] = ((arr4[2] & 0x03) << 6) + arr4[3]; - for(uint8_t i = 0; i < (tidx - 1); i++) pOutputData.push_back(arr3[i]); - } -} - -void AMFImporter::ParseFile(const std::string& pFile, IOSystem* pIOHandler) -{ - irr::io::IrrXMLReader* OldReader = mReader;// store current XMLreader. - std::unique_ptr file(pIOHandler->Open(pFile, "rb")); - - // Check whether we can read from the file - if (file.get() == nullptr) { - throw DeadlyImportError("Failed to open AMF file " + pFile + "."); - } - - // generate a XML reader for it - std::unique_ptr mIOWrapper(new CIrrXML_IOStreamReader(file.get())); - mReader = irr::io::createIrrXMLReader(mIOWrapper.get()); - if(!mReader) throw DeadlyImportError("Failed to create XML reader for file" + pFile + "."); - // - // start reading - // search for root tag - if(XML_SearchNode("amf")) - ParseNode_Root(); - else - throw DeadlyImportError("Root node \"amf\" not found."); - - delete mReader; - // restore old XMLreader - mReader = OldReader; -} - -// -// -// Root XML element. -// Multi elements - No. -void AMFImporter::ParseNode_Root() -{ - std::string unit, version; - CAMFImporter_NodeElement *ne( nullptr ); - - // Read attributes for node . - MACRO_ATTRREAD_LOOPBEG; - MACRO_ATTRREAD_CHECK_RET("unit", unit, mReader->getAttributeValue); - MACRO_ATTRREAD_CHECK_RET("version", version, mReader->getAttributeValue); - MACRO_ATTRREAD_LOOPEND_WSKIP; - - // Check attributes - if(!mUnit.empty()) - { - if((mUnit != "inch") && (mUnit != "millimeter") && (mUnit != "meter") && (mUnit != "feet") && (mUnit != "micron")) Throw_IncorrectAttrValue("unit"); - } - - // create root node element. - ne = new CAMFImporter_NodeElement_Root(nullptr); - mNodeElement_Cur = ne;// set first "current" element - // and assign attribute's values - ((CAMFImporter_NodeElement_Root*)ne)->Unit = unit; - ((CAMFImporter_NodeElement_Root*)ne)->Version = version; - - // Check for child nodes - if(!mReader->isEmptyElement()) - { - MACRO_NODECHECK_LOOPBEGIN("amf"); - if(XML_CheckNode_NameEqual("object")) { ParseNode_Object(); continue; } - if(XML_CheckNode_NameEqual("material")) { ParseNode_Material(); continue; } - if(XML_CheckNode_NameEqual("texture")) { ParseNode_Texture(); continue; } - if(XML_CheckNode_NameEqual("constellation")) { ParseNode_Constellation(); continue; } - if(XML_CheckNode_NameEqual("metadata")) { ParseNode_Metadata(); continue; } - MACRO_NODECHECK_LOOPEND("amf"); - mNodeElement_Cur = ne;// force restore "current" element - }// if(!mReader->isEmptyElement()) - - mNodeElement_List.push_back(ne);// add to node element list because its a new object in graph. -} - -// -// -// A collection of objects or constellations with specific relative locations. -// Multi elements - Yes. -// Parent element - . -void AMFImporter::ParseNode_Constellation() -{ - std::string id; - CAMFImporter_NodeElement* ne( nullptr ); - - // Read attributes for node . - MACRO_ATTRREAD_LOOPBEG; - MACRO_ATTRREAD_CHECK_RET("id", id, mReader->getAttributeValue); - MACRO_ATTRREAD_LOOPEND; - - // create and if needed - define new grouping object. - ne = new CAMFImporter_NodeElement_Constellation(mNodeElement_Cur); - - CAMFImporter_NodeElement_Constellation& als = *((CAMFImporter_NodeElement_Constellation*)ne);// alias for convenience - - if(!id.empty()) als.ID = id; - // Check for child nodes - if(!mReader->isEmptyElement()) - { - ParseHelper_Node_Enter(ne); - MACRO_NODECHECK_LOOPBEGIN("constellation"); - if(XML_CheckNode_NameEqual("instance")) { ParseNode_Instance(); continue; } - if(XML_CheckNode_NameEqual("metadata")) { ParseNode_Metadata(); continue; } - MACRO_NODECHECK_LOOPEND("constellation"); - ParseHelper_Node_Exit(); - }// if(!mReader->isEmptyElement()) - else - { - mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element - }// if(!mReader->isEmptyElement()) else - - mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph. -} - -// -// -// A collection of objects or constellations with specific relative locations. -// Multi elements - Yes. -// Parent element - . -void AMFImporter::ParseNode_Instance() -{ - std::string objectid; - CAMFImporter_NodeElement* ne( nullptr ); - - // Read attributes for node . - MACRO_ATTRREAD_LOOPBEG; - MACRO_ATTRREAD_CHECK_RET("objectid", objectid, mReader->getAttributeValue); - MACRO_ATTRREAD_LOOPEND; - - // used object id must be defined, check that. - if(objectid.empty()) throw DeadlyImportError("\"objectid\" in must be defined."); - // create and define new grouping object. - ne = new CAMFImporter_NodeElement_Instance(mNodeElement_Cur); - - CAMFImporter_NodeElement_Instance& als = *((CAMFImporter_NodeElement_Instance*)ne);// alias for convenience - - als.ObjectID = objectid; - // Check for child nodes - if(!mReader->isEmptyElement()) - { - bool read_flag[6] = { false, false, false, false, false, false }; - - als.Delta.Set(0, 0, 0); - als.Rotation.Set(0, 0, 0); - ParseHelper_Node_Enter(ne); - MACRO_NODECHECK_LOOPBEGIN("instance"); - MACRO_NODECHECK_READCOMP_F("deltax", read_flag[0], als.Delta.x); - MACRO_NODECHECK_READCOMP_F("deltay", read_flag[1], als.Delta.y); - MACRO_NODECHECK_READCOMP_F("deltaz", read_flag[2], als.Delta.z); - MACRO_NODECHECK_READCOMP_F("rx", read_flag[3], als.Rotation.x); - MACRO_NODECHECK_READCOMP_F("ry", read_flag[4], als.Rotation.y); - MACRO_NODECHECK_READCOMP_F("rz", read_flag[5], als.Rotation.z); - MACRO_NODECHECK_LOOPEND("instance"); - ParseHelper_Node_Exit(); - // also convert degrees to radians. - als.Rotation.x = AI_MATH_PI_F * als.Rotation.x / 180.0f; - als.Rotation.y = AI_MATH_PI_F * als.Rotation.y / 180.0f; - als.Rotation.z = AI_MATH_PI_F * als.Rotation.z / 180.0f; - }// if(!mReader->isEmptyElement()) - else - { - mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element - }// if(!mReader->isEmptyElement()) else - - mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph. -} - -// -// -// An object definition. -// Multi elements - Yes. -// Parent element - . -void AMFImporter::ParseNode_Object() -{ - std::string id; - CAMFImporter_NodeElement* ne( nullptr ); - - // Read attributes for node . - MACRO_ATTRREAD_LOOPBEG; - MACRO_ATTRREAD_CHECK_RET("id", id, mReader->getAttributeValue); - MACRO_ATTRREAD_LOOPEND; - - // create and if needed - define new geometry object. - ne = new CAMFImporter_NodeElement_Object(mNodeElement_Cur); - - CAMFImporter_NodeElement_Object& als = *((CAMFImporter_NodeElement_Object*)ne);// alias for convenience - - if(!id.empty()) als.ID = id; - // Check for child nodes - if(!mReader->isEmptyElement()) - { - bool col_read = false; - - ParseHelper_Node_Enter(ne); - MACRO_NODECHECK_LOOPBEGIN("object"); - if(XML_CheckNode_NameEqual("color")) - { - // Check if color already defined for object. - if(col_read) Throw_MoreThanOnceDefined("color", "Only one color can be defined for ."); - // read data and set flag about it - ParseNode_Color(); - col_read = true; - - continue; - } - - if(XML_CheckNode_NameEqual("mesh")) { ParseNode_Mesh(); continue; } - if(XML_CheckNode_NameEqual("metadata")) { ParseNode_Metadata(); continue; } - MACRO_NODECHECK_LOOPEND("object"); - ParseHelper_Node_Exit(); - }// if(!mReader->isEmptyElement()) - else - { - mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element - }// if(!mReader->isEmptyElement()) else - - mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph. -} - -// -// -// Specify additional information about an entity. -// Multi elements - Yes. -// Parent element - , , , , . -// -// Reserved types are: -// "Name" - The alphanumeric label of the entity, to be used by the interpreter if interacting with the user. -// "Description" - A description of the content of the entity -// "URL" - A link to an external resource relating to the entity -// "Author" - Specifies the name(s) of the author(s) of the entity -// "Company" - Specifying the company generating the entity -// "CAD" - specifies the name of the originating CAD software and version -// "Revision" - specifies the revision of the entity -// "Tolerance" - specifies the desired manufacturing tolerance of the entity in entity's unit system -// "Volume" - specifies the total volume of the entity, in the entity's unit system, to be used for verification (object and volume only) -void AMFImporter::ParseNode_Metadata() -{ - std::string type, value; - CAMFImporter_NodeElement* ne( nullptr ); - - // read attribute - MACRO_ATTRREAD_LOOPBEG; - MACRO_ATTRREAD_CHECK_RET("type", type, mReader->getAttributeValue); - MACRO_ATTRREAD_LOOPEND; - // and value of node. - value = mReader->getNodeData(); - // Create node element and assign read data. - ne = new CAMFImporter_NodeElement_Metadata(mNodeElement_Cur); - ((CAMFImporter_NodeElement_Metadata*)ne)->Type = type; - ((CAMFImporter_NodeElement_Metadata*)ne)->Value = value; - mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element - mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph. -} - -/*********************************************************************************************************************************************/ -/******************************************************** Functions: BaseImporter set ********************************************************/ -/*********************************************************************************************************************************************/ - -bool AMFImporter::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool pCheckSig) const -{ - const std::string extension = GetExtension(pFile); - - if ( extension == "amf" ) { - return true; - } - - if(!extension.length() || pCheckSig) - { - const char* tokens[] = { "& pExtensionList) -{ - pExtensionList.insert("amf"); -} - -const aiImporterDesc* AMFImporter::GetInfo () const -{ - return &Description; -} - -void AMFImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) -{ - Clear();// delete old graph. - ParseFile(pFile, pIOHandler); - Postprocess_BuildScene(pScene); - // scene graph is ready, exit. -} - -}// namespace Assimp - -#endif // !ASSIMP_BUILD_NO_AMF_IMPORTER From 51150cb3dfa13afaf829b005b68fae00253a7c96 Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Thu, 2 Jul 2020 14:53:29 +0100 Subject: [PATCH 58/62] Ensure asserts are defined where expected. --- code/PostProcessing/ArmaturePopulate.cpp | 1 - include/assimp/ai_assert.h | 4 +++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/code/PostProcessing/ArmaturePopulate.cpp b/code/PostProcessing/ArmaturePopulate.cpp index 97feca31c..48dcecb15 100644 --- a/code/PostProcessing/ArmaturePopulate.cpp +++ b/code/PostProcessing/ArmaturePopulate.cpp @@ -168,7 +168,6 @@ void ArmaturePopulate::BuildBoneStack(aiNode *, const std::vector &bones, std::map &bone_stack, std::vector &node_stack) { - ai_assert(scene); ai_assert(root_node); ai_assert(!node_stack.empty()); diff --git a/include/assimp/ai_assert.h b/include/assimp/ai_assert.h index 8b2b396f4..195ebbfd0 100644 --- a/include/assimp/ai_assert.h +++ b/include/assimp/ai_assert.h @@ -42,12 +42,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_ASSERT_H_INC #define AI_ASSERT_H_INC +#include + #if defined(ASSIMP_BUILD_DEBUG) namespace Assimp { // Assert violation behavior can be customized: see AssertHandler.h. - void aiAssertViolation(const char* failedExpression, const char* file, int line); + ASSIMP_API void aiAssertViolation(const char* failedExpression, const char* file, int line); } # define ai_assert(expression) (void)((!!(expression)) || (Assimp::aiAssertViolation(#expression, __FILE__, __LINE__), 0)) From 3fb7747429c2f773fc40dd6e437a1da9cbbae9b7 Mon Sep 17 00:00:00 2001 From: Hill Ma Date: Fri, 3 Jul 2020 18:14:45 -0700 Subject: [PATCH 59/62] Improve ToBinary() for double precision. The constant 0x80000000 is specific to 32 bit types. Make the bit mask according to the size of types. --- code/Common/SpatialSort.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/code/Common/SpatialSort.cpp b/code/Common/SpatialSort.cpp index 3b8a64606..88f06b618 100644 --- a/code/Common/SpatialSort.cpp +++ b/code/Common/SpatialSort.cpp @@ -208,13 +208,14 @@ BinFloat ToBinary(const ai_real &pValue) { // floating-point numbers are of sign-magnitude format, so find out what signed number // representation we must convert negative values to. // See http://en.wikipedia.org/wiki/Signed_number_representations. + const BinFloat mask = BinFloat(1) << (CHAR_BIT * sizeof(BinFloat) - 1); // Two's complement? - const bool DefaultValue = ((-42 == (~42 + 1)) && (binValue & 0x80000000)); - const bool OneComplement = ((-42 == ~42) && (binValue & 0x80000000)); + const bool DefaultValue = ((-42 == (~42 + 1)) && (binValue & mask)); + const bool OneComplement = ((-42 == ~42) && (binValue & mask)); if (DefaultValue) - return BinFloat(BinFloat(1) << (CHAR_BIT * sizeof(BinFloat) - 1)) - binValue; + return mask - binValue; // One's complement? else if (OneComplement) return BinFloat(-0) - binValue; From 9aa468262f615dee390e3ce1bf34cdc14a676fa5 Mon Sep 17 00:00:00 2001 From: kimkulling Date: Tue, 7 Jul 2020 17:35:03 +0200 Subject: [PATCH 60/62] closes https://github.com/assimp/assimp/issues/3252: fix build. --- code/AssetLib/3DS/3DSHelper.h | 2 +- code/AssetLib/IFC/IFCReaderGen_2x3.h | 2 +- code/AssetLib/M3D/m3d.h | 4 +++- code/AssetLib/MDL/HalfLife/HL1MDLLoader.cpp | 4 ++-- code/AssetLib/Step/STEPFile.h | 6 +++--- code/Common/Exporter.cpp | 4 ++-- code/Common/Subdivision.cpp | 2 +- 7 files changed, 13 insertions(+), 11 deletions(-) diff --git a/code/AssetLib/3DS/3DSHelper.h b/code/AssetLib/3DS/3DSHelper.h index 89c15f5f2..3ccb1fd07 100644 --- a/code/AssetLib/3DS/3DSHelper.h +++ b/code/AssetLib/3DS/3DSHelper.h @@ -321,7 +321,7 @@ public: struct Face : public FaceWithSmoothingGroup { }; -#ifdef _WIN32 +#if _MSC_VER > 1920 #pragma warning(disable : 4315) #endif diff --git a/code/AssetLib/IFC/IFCReaderGen_2x3.h b/code/AssetLib/IFC/IFCReaderGen_2x3.h index 8ae623dd8..b3f71a7f1 100644 --- a/code/AssetLib/IFC/IFCReaderGen_2x3.h +++ b/code/AssetLib/IFC/IFCReaderGen_2x3.h @@ -45,7 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "AssetLib/Step/STEPFile.h" -#ifdef _WIN32 +#if _MSC_VER > 1920 # pragma warning( disable : 4512 ) #endif // _WIN32 diff --git a/code/AssetLib/M3D/m3d.h b/code/AssetLib/M3D/m3d.h index 3d7a2564c..5ab3d16de 100644 --- a/code/AssetLib/M3D/m3d.h +++ b/code/AssetLib/M3D/m3d.h @@ -85,7 +85,9 @@ typedef uint16_t M3D_INDEX; #define M3D_BONEMAXLEVEL 8 #endif #ifndef _MSC_VER +#ifndef _inline #define _inline __inline__ +#endif #define _pack __attribute__((packed)) #define _unused __attribute__((unused)) #else @@ -99,7 +101,7 @@ typedef uint16_t M3D_INDEX; #define _register #endif -#ifdef _WIN32 +#if _MSC_VER > 1920 # pragma warning(push) # pragma warning(disable : 4100 4127 4189 4505 4244 4403 4701 4703) # if (_MSC_VER > 1800 ) diff --git a/code/AssetLib/MDL/HalfLife/HL1MDLLoader.cpp b/code/AssetLib/MDL/HalfLife/HL1MDLLoader.cpp index 2bb7b42ee..e9930dfed 100644 --- a/code/AssetLib/MDL/HalfLife/HL1MDLLoader.cpp +++ b/code/AssetLib/MDL/HalfLife/HL1MDLLoader.cpp @@ -68,8 +68,8 @@ namespace Assimp { namespace MDL { namespace HalfLife { -#ifdef _WIN32 -# pragma warning(disable : 4706) +#if _MSC_VER > 1920 +# pragma warning(disable : 4706) #endif // _WIN32 // ------------------------------------------------------------------------------------------------ diff --git a/code/AssetLib/Step/STEPFile.h b/code/AssetLib/Step/STEPFile.h index 1448c107f..72648e462 100644 --- a/code/AssetLib/Step/STEPFile.h +++ b/code/AssetLib/Step/STEPFile.h @@ -54,7 +54,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include -#ifdef _WIN32 +#if _MSC_VER > 1920 # pragma warning(push) # pragma warning(disable : 4127 4456 4245 4512 ) #endif // _WIN32 @@ -727,7 +727,7 @@ struct InternGenericConvert> { } }; -#ifdef _WIN32 +#if _MSC_VER > 1920 #pragma warning(push) #pragma warning(disable : 4127) #endif // _WIN32 @@ -960,7 +960,7 @@ private: const EXPRESS::ConversionSchema *schema; }; -#ifdef _WIN32 +#if _MSC_VER > 1920 #pragma warning(pop) #endif // _WIN32 diff --git a/code/Common/Exporter.cpp b/code/Common/Exporter.cpp index 58fc01d91..a47c52a6c 100644 --- a/code/Common/Exporter.cpp +++ b/code/Common/Exporter.cpp @@ -74,8 +74,8 @@ Here we implement only the C++ interface (Assimp::Exporter). namespace Assimp { -#ifdef _WIN32 -# pragma warning( disable : 4800 ) +#if _MSC_VER > 1920 +# pragma warning( disable : 4800 ) #endif // _WIN32 diff --git a/code/Common/Subdivision.cpp b/code/Common/Subdivision.cpp index b1f07c9f5..4f64a00c4 100644 --- a/code/Common/Subdivision.cpp +++ b/code/Common/Subdivision.cpp @@ -53,7 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using namespace Assimp; void mydummy() {} -#ifdef _WIN32 +#if _MSC_VER > 1920 #pragma warning(disable : 4709) #endif // _WIN32 // ------------------------------------------------------------------------------------------------ From b8ec93aa2137d18e8fb861df17fb6878b8e7d656 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 11 Jul 2020 22:34:43 +0200 Subject: [PATCH 61/62] use c-styl cast in a c-file --- samples/SimpleOpenGL/Sample_SimpleOpenGL.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/SimpleOpenGL/Sample_SimpleOpenGL.c b/samples/SimpleOpenGL/Sample_SimpleOpenGL.c index 01704a1e4..bcb109564 100644 --- a/samples/SimpleOpenGL/Sample_SimpleOpenGL.c +++ b/samples/SimpleOpenGL/Sample_SimpleOpenGL.c @@ -278,7 +278,7 @@ void do_motion (void) static int frames = 0; int time = glutGet(GLUT_ELAPSED_TIME); - angle += static_cast((time-prev_time)*0.01); + angle += (float)((time-prev_time)*0.01); prev_time = time; frames += 1; From 108b3a62e5b1ace725f3ddee06a701eddc19199e Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 11 Jul 2020 22:45:45 +0200 Subject: [PATCH 62/62] Update Exporter.hpp revert merge issue --- include/assimp/Exporter.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/assimp/Exporter.hpp b/include/assimp/Exporter.hpp index 6fcbafe92..15918dd47 100644 --- a/include/assimp/Exporter.hpp +++ b/include/assimp/Exporter.hpp @@ -110,9 +110,9 @@ public: ExportFormatEntry() : mExportFunction(), mEnforcePP() { - mDescription.id = NULL; - mDescription.description = NULL; - mDescription.fileExtension = NULL; + mDescription.id = nullptr; + mDescription.description = nullptr; + mDescription.fileExtension = nullptr; } };