diff --git a/code/AssetLib/Blender/BlenderLoader.cpp b/code/AssetLib/Blender/BlenderLoader.cpp index 4b094936c..04c911757 100644 --- a/code/AssetLib/Blender/BlenderLoader.cpp +++ b/code/AssetLib/Blender/BlenderLoader.cpp @@ -318,42 +318,81 @@ void BlenderImporter::ExtractScene(Scene &out, const FileDatabase &file) { #endif } +// ------------------------------------------------------------------------------------------------ +void BlenderImporter::ParseSubCollection(const Blender::Scene &in, aiNode *root, std::shared_ptr collection, ConversionData &conv_data) { + + std::deque root_objects; + // Count number of objects + for (std::shared_ptr cur = std::static_pointer_cast(collection->gobject.first); cur; cur = cur->next) { + if (cur->ob) { + root_objects.push_back(cur->ob); + } + } + std::deque root_children; + // Count number of child nodes + for (std::shared_ptr cur = std::static_pointer_cast(collection->children.first); cur; cur = cur->next) { + if (cur->collection) { + root_children.push_back(cur->collection.get()); + } + } + root->mNumChildren = static_cast(root_objects.size() + root_children.size()); + root->mChildren = new aiNode *[root->mNumChildren](); + + for (unsigned int i = 0; i < static_cast(root_objects.size()); ++i) { + root->mChildren[i] = ConvertNode(in, root_objects[i], conv_data, aiMatrix4x4()); + root->mChildren[i]->mParent = root; + } + + // For each subcollection create a new node to represent it + unsigned int iterator = static_cast(root_objects.size()); + for (std::shared_ptr cur = std::static_pointer_cast(collection->children.first); cur; cur = cur->next) { + if (cur->collection) { + root->mChildren[iterator] = new aiNode(cur->collection->id.name + 2); // skip over the name prefix 'OB' + root->mChildren[iterator]->mParent = root; + ParseSubCollection(in, root->mChildren[iterator], cur->collection, conv_data); + } + iterator += 1; + } +} + // ------------------------------------------------------------------------------------------------ void BlenderImporter::ConvertBlendFile(aiScene *out, const Scene &in, const FileDatabase &file) { ConversionData conv(file); - // FIXME it must be possible to take the hierarchy directly from - // the file. This is terrible. Here, we're first looking for - // all objects which don't have parent objects at all - - std::deque no_parents; - for (std::shared_ptr cur = std::static_pointer_cast(in.base.first); cur; cur = cur->next) { - if (cur->object) { - if (!cur->object->parent) { - no_parents.push_back(cur->object.get()); - } else { - conv.objects.insert(cur->object.get()); - } - } - } - for (std::shared_ptr cur = in.basact; cur; cur = cur->next) { - if (cur->object) { - if (cur->object->parent) { - conv.objects.insert(cur->object.get()); - } - } - } - - if (no_parents.empty()) { - ThrowException("Expected at least one object with no parent"); - } - aiNode *root = out->mRootNode = new aiNode(""); + // Iterate over all objects directly under master_collection, + // If in.master_collection == null, then we're parsing something older. + if (in.master_collection) { + ParseSubCollection(in, root, in.master_collection, conv); + } else { + std::deque no_parents; + for (std::shared_ptr cur = std::static_pointer_cast(in.base.first); cur; cur = cur->next) { + if (cur->object) { + if (!cur->object->parent) { + no_parents.push_back(cur->object.get()); + } else { + conv.objects.insert(cur->object.get()); + } + } + } + for (std::shared_ptr cur = in.basact; cur; cur = cur->next) { + if (cur->object) { + if (cur->object->parent) { + conv.objects.insert(cur->object.get()); + } + } + } - root->mNumChildren = static_cast(no_parents.size()); - root->mChildren = new aiNode *[root->mNumChildren](); - for (unsigned int i = 0; i < root->mNumChildren; ++i) { - root->mChildren[i] = ConvertNode(in, no_parents[i], conv, aiMatrix4x4()); - root->mChildren[i]->mParent = root; + if (no_parents.empty()) { + ThrowException("Expected at least one object with no parent"); + } + + root->mNumChildren = static_cast(no_parents.size()); + root->mChildren = new aiNode *[root->mNumChildren](); + for (unsigned int i = 0; i < root->mNumChildren; ++i) { + root->mChildren[i] = ConvertNode(in, no_parents[i], conv, aiMatrix4x4()); + root->mChildren[i]->mParent = root; + } } BuildMaterials(conv); diff --git a/code/AssetLib/Blender/BlenderLoader.h b/code/AssetLib/Blender/BlenderLoader.h index 1df0fcf90..94f034cd1 100644 --- a/code/AssetLib/Blender/BlenderLoader.h +++ b/code/AssetLib/Blender/BlenderLoader.h @@ -78,6 +78,7 @@ struct ElemBase; namespace Blender { struct Scene; struct Object; +struct Collection; struct Mesh; struct Camera; struct Lamp; @@ -116,6 +117,7 @@ protected: void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) override; void ParseBlendFile(Blender::FileDatabase &out, std::shared_ptr stream); void ExtractScene(Blender::Scene &out, const Blender::FileDatabase &file); + void ParseSubCollection(const Blender::Scene &in, aiNode *root, std::shared_ptr collection, Blender::ConversionData &conv_data); void ConvertBlendFile(aiScene *out, const Blender::Scene &in, const Blender::FileDatabase &file); private: diff --git a/code/AssetLib/Blender/BlenderScene.cpp b/code/AssetLib/Blender/BlenderScene.cpp index c654b5b14..c93d913fc 100644 --- a/code/AssetLib/Blender/BlenderScene.cpp +++ b/code/AssetLib/Blender/BlenderScene.cpp @@ -94,6 +94,52 @@ void Structure ::Convert( db.reader->IncPtr(size); } +//-------------------------------------------------------------------------------- +template <> +void Structure::Convert( + CollectionObject &dest, + const FileDatabase &db) const { + + ReadFieldPtr(dest.next, "*next", db); + { + //std::shared_ptr prev; + //ReadFieldPtr(prev, "*prev", db); + //dest.prev = prev.get(); + + std::shared_ptr ob; + ReadFieldPtr(ob, "*ob", db); + dest.ob = ob.get(); + } + + db.reader->IncPtr(size); +} + +//-------------------------------------------------------------------------------- +template <> +void Structure::Convert( + CollectionChild &dest, + const FileDatabase &db) const { + + ReadFieldPtr(dest.prev, "*prev", db); + ReadFieldPtr(dest.next, "*next", db); + ReadFieldPtr(dest.collection, "*collection", db); + + db.reader->IncPtr(size); +} + +//-------------------------------------------------------------------------------- +template <> +void Structure::Convert( + Collection &dest, + const FileDatabase &db) const { + + ReadField(dest.id, "id", db); + ReadField(dest.gobject, "gobject", db); + ReadField(dest.children, "children", db); + + db.reader->IncPtr(size); +} + //-------------------------------------------------------------------------------- template <> void Structure ::Convert( @@ -660,6 +706,7 @@ void Structure ::Convert( ReadFieldPtr(dest.camera, "*camera", db); ReadFieldPtr(dest.world, "*world", db); ReadFieldPtr(dest.basact, "*basact", db); + ReadFieldPtr(dest.master_collection, "*master_collection", db); ReadField(dest.base, "base", db); db.reader->IncPtr(size); @@ -833,6 +880,9 @@ void DNA::RegisterConverters() { converters["Image"] = DNA::FactoryPair(&Structure::Allocate, &Structure::Convert); converters["CustomData"] = DNA::FactoryPair(&Structure::Allocate, &Structure::Convert); converters["CustomDataLayer"] = DNA::FactoryPair(&Structure::Allocate, &Structure::Convert); + converters["Collection"] = DNA::FactoryPair(&Structure::Allocate, &Structure::Convert); + converters["CollectionChild"] = DNA::FactoryPair(&Structure::Allocate, &Structure::Convert); + converters["CollectionObject"] = DNA::FactoryPair(&Structure::Allocate, &Structure::Convert); } #endif // ASSIMP_BUILD_NO_BLEND_IMPORTER diff --git a/code/AssetLib/Blender/BlenderScene.h b/code/AssetLib/Blender/BlenderScene.h index 50dda28c8..ebc6a27e6 100644 --- a/code/AssetLib/Blender/BlenderScene.h +++ b/code/AssetLib/Blender/BlenderScene.h @@ -107,6 +107,7 @@ namespace Blender { struct Object; struct MTex; struct Image; +struct Collection; #include @@ -147,6 +148,26 @@ struct Group : ElemBase { std::shared_ptr gobject; }; +// ------------------------------------------------------------------------------- +struct CollectionObject : ElemBase { + //CollectionObject* prev; + std::shared_ptr next; + Object *ob; +}; + +// ------------------------------------------------------------------------------- +struct CollectionChild : ElemBase { + std::shared_ptr next, prev; + std::shared_ptr collection; +}; + +// ------------------------------------------------------------------------------- +struct Collection : ElemBase { + ID id FAIL; + ListBase gobject; // CollectionObject + ListBase children; // CollectionChild +}; + // ------------------------------------------------------------------------------- struct World : ElemBase { ID id FAIL; @@ -729,11 +750,12 @@ struct Scene : ElemBase { std::shared_ptr camera WARN; std::shared_ptr world WARN; std::shared_ptr basact WARN; + std::shared_ptr master_collection WARN; ListBase base; Scene() : - ElemBase(), camera(), world(), basact() { + ElemBase(), camera(), world(), basact(), master_collection() { // empty } }; diff --git a/code/AssetLib/Blender/BlenderSceneGen.h b/code/AssetLib/Blender/BlenderSceneGen.h index 0c93d17a3..762fdd33b 100644 --- a/code/AssetLib/Blender/BlenderSceneGen.h +++ b/code/AssetLib/Blender/BlenderSceneGen.h @@ -62,6 +62,12 @@ template <> void Structure :: Convert ( ) const ; +template <> void Structure::Convert( + Collection& dest, + const FileDatabase& db + ) const +; + template <> void Structure :: Convert ( MTex& dest, const FileDatabase& db diff --git a/code/AssetLib/FBX/FBXConverter.cpp b/code/AssetLib/FBX/FBXConverter.cpp index d4500fb31..098ba58e2 100644 --- a/code/AssetLib/FBX/FBXConverter.cpp +++ b/code/AssetLib/FBX/FBXConverter.cpp @@ -3127,7 +3127,12 @@ aiNodeAnim* FBXConverter::GenerateSimpleNodeAnim(const std::string& name, if (chain[i] == iterEnd) continue; - keyframeLists[i] = GetKeyframeList((*chain[i]).second, start, stop); + if (i == TransformationComp_Rotation || i == TransformationComp_PreRotation + || i == TransformationComp_PostRotation || i == TransformationComp_GeometricRotation) { + keyframeLists[i] = GetRotationKeyframeList((*chain[i]).second, start, stop); + } else { + keyframeLists[i] = GetKeyframeList((*chain[i]).second, start, stop); + } for (KeyFrameListList::const_iterator it = keyframeLists[i].begin(); it != keyframeLists[i].end(); ++it) { const KeyTimeList& times = *std::get<0>(*it); @@ -3274,6 +3279,79 @@ FBXConverter::KeyFrameListList FBXConverter::GetKeyframeList(const std::vector &nodes, + int64_t start, int64_t stop) { + KeyFrameListList inputs; + inputs.reserve(nodes.size() * 3); + + //give some breathing room for rounding errors + const int64_t adj_start = start - 10000; + const int64_t adj_stop = stop + 10000; + + for (const AnimationCurveNode *node : nodes) { + ai_assert(node); + + const AnimationCurveMap &curves = node->Curves(); + for (const AnimationCurveMap::value_type &kv : curves) { + + unsigned int mapto; + if (kv.first == "d|X") { + mapto = 0; + } else if (kv.first == "d|Y") { + mapto = 1; + } else if (kv.first == "d|Z") { + mapto = 2; + } else { + FBXImporter::LogWarn("ignoring scale animation curve, did not recognize target component"); + continue; + } + + const AnimationCurve *const curve = kv.second; + ai_assert(curve->GetKeys().size() == curve->GetValues().size()); + ai_assert(curve->GetKeys().size()); + + //get values within the start/stop time window + std::shared_ptr Keys(new KeyTimeList()); + std::shared_ptr Values(new KeyValueList()); + const size_t count = curve->GetKeys().size(); + + int64_t tp = curve->GetKeys().at(0); + float vp = curve->GetValues().at(0); + Keys->push_back(tp); + Values->push_back(vp); + if (count > 1) { + int64_t tc = curve->GetKeys().at(1); + float vc = curve->GetValues().at(1); + for (size_t n = 1; n < count; n++) { + while (std::abs(vc - vp) >= 180.0f) { + float step = std::floor(float(tc - tp) / (vc - vp) * 179.0f); + int64_t tnew = tp + int64_t(step); + float vnew = vp + (vc - vp) * step / float(tc - tp); + if (tnew >= adj_start && tnew <= adj_stop) { + Keys->push_back(tnew); + Values->push_back(vnew); + } + tp = tnew; + vp = vnew; + } + if (tc >= adj_start && tc <= adj_stop) { + Keys->push_back(tc); + Values->push_back(vc); + } + if (n + 1 < count) { + tp = tc; + vp = vc; + tc = curve->GetKeys().at(n + 1); + vc = curve->GetValues().at(n + 1); + } + } + } + inputs.push_back(std::make_tuple(Keys, Values, mapto)); + } + } + return inputs; +} + KeyTimeList FBXConverter::GetKeyTimeList(const KeyFrameListList &inputs) { ai_assert(!inputs.empty()); @@ -3464,7 +3542,7 @@ void FBXConverter::ConvertRotationKeys(aiNodeAnim *na, const std::vector &inputs = GetKeyframeList(nodes, start, stop); + const std::vector &inputs = GetRotationKeyframeList(nodes, start, stop); const KeyTimeList &keys = GetKeyTimeList(inputs); na->mNumRotationKeys = static_cast(keys.size()); diff --git a/code/AssetLib/FBX/FBXConverter.h b/code/AssetLib/FBX/FBXConverter.h index b9a494695..20aaa4435 100644 --- a/code/AssetLib/FBX/FBXConverter.h +++ b/code/AssetLib/FBX/FBXConverter.h @@ -361,6 +361,7 @@ private: // ------------------------------------------------------------------------------------------------ KeyFrameListList GetKeyframeList(const std::vector& nodes, int64_t start, int64_t stop); + KeyFrameListList GetRotationKeyframeList(const std::vector& nodes, int64_t start, int64_t stop); // ------------------------------------------------------------------------------------------------ KeyTimeList GetKeyTimeList(const KeyFrameListList& inputs); diff --git a/code/AssetLib/X3D/X3DImporter.cpp b/code/AssetLib/X3D/X3DImporter.cpp index e33782785..b8b9d250e 100644 --- a/code/AssetLib/X3D/X3DImporter.cpp +++ b/code/AssetLib/X3D/X3DImporter.cpp @@ -235,10 +235,8 @@ void X3DImporter::ParseFile(const std::string &file, IOSystem *pIOHandler) { bool X3DImporter::CanRead(const std::string &pFile, IOSystem * /*pIOHandler*/, bool checkSig) const { if (checkSig) { - std::string::size_type pos = pFile.find_last_of(".x3d"); - if (pos != std::string::npos) { + if (GetExtension(pFile) == "x3d") return true; - } } return false; diff --git a/code/AssetLib/X3D/X3DImporter_Group.cpp b/code/AssetLib/X3D/X3DImporter_Group.cpp index f579dc517..e7a2e917e 100644 --- a/code/AssetLib/X3D/X3DImporter_Group.cpp +++ b/code/AssetLib/X3D/X3DImporter_Group.cpp @@ -72,7 +72,7 @@ void X3DImporter::startReadGroup(XmlNode &node) { // if "USE" defined then find already defined element. if (!use.empty()) { - X3DNodeElementBase *ne = nullptr; + X3DNodeElementBase *ne(nullptr); ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Group, ne); } else { ParseHelper_Group_Begin(); // create new grouping element and go deeper if node has children. @@ -110,7 +110,7 @@ void X3DImporter::startReadStaticGroup(XmlNode &node) { // if "USE" defined then find already defined element. if (!use.empty()) { - X3DNodeElementBase *ne = nullptr; + X3DNodeElementBase *ne(nullptr); ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Group, ne); } else { @@ -153,7 +153,7 @@ void X3DImporter::startReadSwitch(XmlNode &node) { // if "USE" defined then find already defined element. if (!use.empty()) { - X3DNodeElementBase *ne=nullptr; + X3DNodeElementBase *ne(nullptr); ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Group, ne); } else { @@ -226,8 +226,13 @@ void X3DImporter::startReadTransform(XmlNode &node) { // if "USE" defined then find already defined element. if (!use.empty()) { X3DNodeElementBase *ne(nullptr); - + bool newgroup = (nullptr == mNodeElementCur); + if(newgroup) + ParseHelper_Group_Begin(); ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Group, ne); + if (newgroup && isNodeEmpty(node)) { + ParseHelper_Node_Exit(); + } } else { ParseHelper_Group_Begin(); // create new grouping element and go deeper if node has children. // at this place new group mode created and made current, so we can name it. diff --git a/code/AssetLib/X3D/X3DImporter_Macro.hpp b/code/AssetLib/X3D/X3DImporter_Macro.hpp index 6d4c61c3f..a84a739a3 100644 --- a/code/AssetLib/X3D/X3DImporter_Macro.hpp +++ b/code/AssetLib/X3D/X3DImporter_Macro.hpp @@ -60,14 +60,12 @@ namespace Assimp { /// \param [in] pType - type of element to find. /// \param [out] pNE - pointer to found node element. inline X3DNodeElementBase *X3DImporter::MACRO_USE_CHECKANDAPPLY(XmlNode &node, std::string pDEF, std::string pUSE, X3DElemType pType, X3DNodeElementBase *pNE) { - if (nullptr == mNodeElementCur) { - printf("here\n"); - } checkNodeMustBeEmpty(node); if (!pDEF.empty()) Assimp::Throw_DEF_And_USE(node.name()); if (!FindNodeElement(pUSE, pType, &pNE)) Assimp::Throw_USE_NotFound(node.name(), pUSE); + ai_assert(nullptr != mNodeElementCur); mNodeElementCur->Children.push_back(pNE); /* add found object as child to current element */ return pNE; diff --git a/code/AssetLib/glTF/glTFCommon.h b/code/AssetLib/glTF/glTFCommon.h index 78d40ce2c..14b82aa29 100644 --- a/code/AssetLib/glTF/glTFCommon.h +++ b/code/AssetLib/glTF/glTFCommon.h @@ -300,7 +300,7 @@ public: inline unsigned int GetIndex() const { return index; } - operator bool() const { return vector != 0; } + operator bool() const { return vector != nullptr && index < vector->size(); } T *operator->() { return (*vector)[index]; } diff --git a/code/AssetLib/glTF2/glTF2Asset.inl b/code/AssetLib/glTF2/glTF2Asset.inl index e0a505297..f35a47efa 100644 --- a/code/AssetLib/glTF2/glTF2Asset.inl +++ b/code/AssetLib/glTF2/glTF2Asset.inl @@ -600,6 +600,10 @@ inline void Buffer::Read(Value &obj, Asset &r) { inline bool Buffer::LoadFromStream(IOStream &stream, size_t length, size_t baseOffset) { byteLength = length ? length : stream.FileSize(); + if (byteLength > stream.FileSize()) { + throw DeadlyImportError("GLTF: Invalid byteLength exceeds size of actual data."); + } + if (baseOffset) { stream.Seek(baseOffset, aiOrigin_SET); } @@ -809,6 +813,11 @@ inline void Accessor::Sparse::PatchData(unsigned int elementSize) { } offset *= elementSize; + + if (offset + elementSize > data.size()) { + throw DeadlyImportError("Invalid sparse accessor. Byte offset for patching points outside allocated memory."); + } + std::memcpy(data.data() + offset, pValues, elementSize); pValues += elementSize; diff --git a/include/assimp/Vertex.h b/include/assimp/Vertex.h index ad5ff476c..f2e5572d3 100644 --- a/include/assimp/Vertex.h +++ b/include/assimp/Vertex.h @@ -135,7 +135,9 @@ public: /** Extract a particular vertex from a anim mesh and interleave all components */ explicit Vertex(const aiAnimMesh* msh, unsigned int idx) { ai_assert(idx < msh->mNumVertices); - position = msh->mVertices[idx]; + if (msh->HasPositions()) { + position = msh->mVertices[idx]; + } if (msh->HasNormals()) { normal = msh->mNormals[idx]; diff --git a/test/models/3DS/UVTransformTest/UVTransformTestImg.png b/test/models/3DS/UVTransformTest/UVTransformTestImg.png deleted file mode 100644 index 020da1772..000000000 Binary files a/test/models/3DS/UVTransformTest/UVTransformTestImg.png and /dev/null differ diff --git a/test/models/3DS/UVTransformTest/UVTransform_Cube.3DS b/test/models/3DS/UVTransformTest/UVTransform_Cube.3DS deleted file mode 100644 index 609817232..000000000 Binary files a/test/models/3DS/UVTransformTest/UVTransform_Cube.3DS and /dev/null differ diff --git a/test/models/3DS/UVTransformTest/UVTransform_Cube_ScaleUV2x_clampUV.3DS b/test/models/3DS/UVTransformTest/UVTransform_Cube_ScaleUV2x_clampUV.3DS deleted file mode 100644 index c76e38f4a..000000000 Binary files a/test/models/3DS/UVTransformTest/UVTransform_Cube_ScaleUV2x_clampUV.3DS and /dev/null differ diff --git a/test/models/3DS/UVTransformTest/UVTransform_Normal.3DS b/test/models/3DS/UVTransformTest/UVTransform_Normal.3DS deleted file mode 100644 index 884d7167f..000000000 Binary files a/test/models/3DS/UVTransformTest/UVTransform_Normal.3DS and /dev/null differ diff --git a/test/models/3DS/UVTransformTest/UVTransform_OffsetU0.56V0.5_ScaleU10V2_Rotate45.3DS b/test/models/3DS/UVTransformTest/UVTransform_OffsetU0.56V0.5_ScaleU10V2_Rotate45.3DS deleted file mode 100644 index 3d3d47fbb..000000000 Binary files a/test/models/3DS/UVTransformTest/UVTransform_OffsetU0.56V0.5_ScaleU10V2_Rotate45.3DS and /dev/null differ diff --git a/test/models/3DS/UVTransformTest/UVTransform_OffsetU0.5_ScaleUV2_Rotate45_clampUV.3DS b/test/models/3DS/UVTransformTest/UVTransform_OffsetU0.5_ScaleUV2_Rotate45_clampUV.3DS deleted file mode 100644 index 1dae8550f..000000000 Binary files a/test/models/3DS/UVTransformTest/UVTransform_OffsetU0.5_ScaleUV2_Rotate45_clampUV.3DS and /dev/null differ diff --git a/test/models/3DS/UVTransformTest/UVTransform_OffsetUV0.5-clampUV.3DS b/test/models/3DS/UVTransformTest/UVTransform_OffsetUV0.5-clampUV.3DS deleted file mode 100644 index 014da9e1b..000000000 Binary files a/test/models/3DS/UVTransformTest/UVTransform_OffsetUV0.5-clampUV.3DS and /dev/null differ diff --git a/test/models/3DS/UVTransformTest/UVTransform_OffsetUV0.5-mirrorUV.3DS b/test/models/3DS/UVTransformTest/UVTransform_OffsetUV0.5-mirrorUV.3DS deleted file mode 100644 index b00b9d611..000000000 Binary files a/test/models/3DS/UVTransformTest/UVTransform_OffsetUV0.5-mirrorUV.3DS and /dev/null differ diff --git a/test/models/3DS/UVTransformTest/UVTransform_OffsetUV0.5.3DS b/test/models/3DS/UVTransformTest/UVTransform_OffsetUV0.5.3DS deleted file mode 100644 index c4622e94c..000000000 Binary files a/test/models/3DS/UVTransformTest/UVTransform_OffsetUV0.5.3DS and /dev/null differ diff --git a/test/models/3DS/UVTransformTest/UVTransform_ScaleUV1-2_OffsetUV0-0.9_Rotate-72_mirrorU.3ds b/test/models/3DS/UVTransformTest/UVTransform_ScaleUV1-2_OffsetUV0-0.9_Rotate-72_mirrorU.3ds deleted file mode 100644 index 1360482d1..000000000 Binary files a/test/models/3DS/UVTransformTest/UVTransform_ScaleUV1-2_OffsetUV0-0.9_Rotate-72_mirrorU.3ds and /dev/null differ diff --git a/test/models/3DS/UVTransformTest/UVTransform_ScaleUV10-2_OffsetUV10-mirrorUV.3DS b/test/models/3DS/UVTransformTest/UVTransform_ScaleUV10-2_OffsetUV10-mirrorUV.3DS deleted file mode 100644 index f24a89ce4..000000000 Binary files a/test/models/3DS/UVTransformTest/UVTransform_ScaleUV10-2_OffsetUV10-mirrorUV.3DS and /dev/null differ diff --git a/test/models/3DS/UVTransformTest/UVTransform_ScaleUV2x.3DS b/test/models/3DS/UVTransformTest/UVTransform_ScaleUV2x.3DS deleted file mode 100644 index 8cafc61f2..000000000 Binary files a/test/models/3DS/UVTransformTest/UVTransform_ScaleUV2x.3DS and /dev/null differ diff --git a/test/models/3DS/UVTransformTest/UVTransform_ScaleUV2x_Rotate45.3DS b/test/models/3DS/UVTransformTest/UVTransform_ScaleUV2x_Rotate45.3DS deleted file mode 100644 index 45640949d..000000000 Binary files a/test/models/3DS/UVTransformTest/UVTransform_ScaleUV2x_Rotate45.3DS and /dev/null differ diff --git a/test/models/3DS/UVTransformTest/note.txt b/test/models/3DS/UVTransformTest/note.txt deleted file mode 100644 index 9a6bab030..000000000 --- a/test/models/3DS/UVTransformTest/note.txt +++ /dev/null @@ -1,11 +0,0 @@ -All 'mirror' files are not absolutely correct. That's mainly -because it's difficult convert Max' handling of mirroring to -our's. - -In other words: TO DO, but only if someone REALLY needs it. - -------------------------------------------------------------- - -To see how it should look like - test/ReferenceImages -Note that the viewer has no 'decal' texture mapping mode, so -the usual clamping is used. diff --git a/test/models/BLEND/BlenderDefault_276.blend b/test/models/BLEND/BlenderDefault_276.blend new file mode 100644 index 000000000..28ebbcc1f Binary files /dev/null and b/test/models/BLEND/BlenderDefault_276.blend differ diff --git a/test/models/BLEND/box.blend b/test/models/BLEND/box.blend index 28ebbcc1f..a41250fdc 100644 Binary files a/test/models/BLEND/box.blend and b/test/models/BLEND/box.blend differ diff --git a/test/unit/utBlenderImportExport.cpp b/test/unit/utBlenderImportExport.cpp index 8a585ed74..9ef1fc693 100644 --- a/test/unit/utBlenderImportExport.cpp +++ b/test/unit/utBlenderImportExport.cpp @@ -114,6 +114,12 @@ TEST(utBlenderImporter, importBlenderDefault271) { ASSERT_NE(nullptr, scene); } +TEST(utBlenderImporter, importBlenderDefault293) { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/BLEND/BlenderDefault_276.blend", aiProcess_ValidateDataStructure); + ASSERT_NE(nullptr, scene); +} + TEST(utBlenderImporter, importCubeHierarchy_248) { Assimp::Importer importer; const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/BLEND/CubeHierarchy_248.blend", aiProcess_ValidateDataStructure);