Merge branch 'master' into ms-maxvollmer/crashfixes2
commit
d6f3f292f2
|
@ -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> collection, ConversionData &conv_data) {
|
||||
|
||||
std::deque<Object *> root_objects;
|
||||
// Count number of objects
|
||||
for (std::shared_ptr<CollectionObject> cur = std::static_pointer_cast<CollectionObject>(collection->gobject.first); cur; cur = cur->next) {
|
||||
if (cur->ob) {
|
||||
root_objects.push_back(cur->ob);
|
||||
}
|
||||
}
|
||||
std::deque<Collection *> root_children;
|
||||
// Count number of child nodes
|
||||
for (std::shared_ptr<CollectionChild> cur = std::static_pointer_cast<CollectionChild>(collection->children.first); cur; cur = cur->next) {
|
||||
if (cur->collection) {
|
||||
root_children.push_back(cur->collection.get());
|
||||
}
|
||||
}
|
||||
root->mNumChildren = static_cast<unsigned int>(root_objects.size() + root_children.size());
|
||||
root->mChildren = new aiNode *[root->mNumChildren]();
|
||||
|
||||
for (unsigned int i = 0; i < static_cast<unsigned int>(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<unsigned int>(root_objects.size());
|
||||
for (std::shared_ptr<CollectionChild> cur = std::static_pointer_cast<CollectionChild>(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<const Object *> no_parents;
|
||||
for (std::shared_ptr<Base> cur = std::static_pointer_cast<Base>(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<Base> 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("<BlenderRoot>");
|
||||
// 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<const Object *> no_parents;
|
||||
for (std::shared_ptr<Base> cur = std::static_pointer_cast<Base>(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<Base> cur = in.basact; cur; cur = cur->next) {
|
||||
if (cur->object) {
|
||||
if (cur->object->parent) {
|
||||
conv.objects.insert(cur->object.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
root->mNumChildren = static_cast<unsigned int>(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<unsigned int>(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);
|
||||
|
|
|
@ -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<IOStream> stream);
|
||||
void ExtractScene(Blender::Scene &out, const Blender::FileDatabase &file);
|
||||
void ParseSubCollection(const Blender::Scene &in, aiNode *root, std::shared_ptr<Blender::Collection> collection, Blender::ConversionData &conv_data);
|
||||
void ConvertBlendFile(aiScene *out, const Blender::Scene &in, const Blender::FileDatabase &file);
|
||||
|
||||
private:
|
||||
|
|
|
@ -94,6 +94,52 @@ void Structure ::Convert<Group>(
|
|||
db.reader->IncPtr(size);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <>
|
||||
void Structure::Convert<CollectionObject>(
|
||||
CollectionObject &dest,
|
||||
const FileDatabase &db) const {
|
||||
|
||||
ReadFieldPtr<ErrorPolicy_Fail>(dest.next, "*next", db);
|
||||
{
|
||||
//std::shared_ptr<CollectionObject> prev;
|
||||
//ReadFieldPtr<ErrorPolicy_Fail>(prev, "*prev", db);
|
||||
//dest.prev = prev.get();
|
||||
|
||||
std::shared_ptr<Object> ob;
|
||||
ReadFieldPtr<ErrorPolicy_Igno>(ob, "*ob", db);
|
||||
dest.ob = ob.get();
|
||||
}
|
||||
|
||||
db.reader->IncPtr(size);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <>
|
||||
void Structure::Convert<CollectionChild>(
|
||||
CollectionChild &dest,
|
||||
const FileDatabase &db) const {
|
||||
|
||||
ReadFieldPtr<ErrorPolicy_Fail>(dest.prev, "*prev", db);
|
||||
ReadFieldPtr<ErrorPolicy_Fail>(dest.next, "*next", db);
|
||||
ReadFieldPtr<ErrorPolicy_Igno>(dest.collection, "*collection", db);
|
||||
|
||||
db.reader->IncPtr(size);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <>
|
||||
void Structure::Convert<Collection>(
|
||||
Collection &dest,
|
||||
const FileDatabase &db) const {
|
||||
|
||||
ReadField<ErrorPolicy_Fail>(dest.id, "id", db);
|
||||
ReadField<ErrorPolicy_Fail>(dest.gobject, "gobject", db);
|
||||
ReadField<ErrorPolicy_Fail>(dest.children, "children", db);
|
||||
|
||||
db.reader->IncPtr(size);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <>
|
||||
void Structure ::Convert<MTex>(
|
||||
|
@ -660,6 +706,7 @@ void Structure ::Convert<Scene>(
|
|||
ReadFieldPtr<ErrorPolicy_Warn>(dest.camera, "*camera", db);
|
||||
ReadFieldPtr<ErrorPolicy_Warn>(dest.world, "*world", db);
|
||||
ReadFieldPtr<ErrorPolicy_Warn>(dest.basact, "*basact", db);
|
||||
ReadFieldPtr<ErrorPolicy_Warn>(dest.master_collection, "*master_collection", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.base, "base", db);
|
||||
|
||||
db.reader->IncPtr(size);
|
||||
|
@ -833,6 +880,9 @@ void DNA::RegisterConverters() {
|
|||
converters["Image"] = DNA::FactoryPair(&Structure::Allocate<Image>, &Structure::Convert<Image>);
|
||||
converters["CustomData"] = DNA::FactoryPair(&Structure::Allocate<CustomData>, &Structure::Convert<CustomData>);
|
||||
converters["CustomDataLayer"] = DNA::FactoryPair(&Structure::Allocate<CustomDataLayer>, &Structure::Convert<CustomDataLayer>);
|
||||
converters["Collection"] = DNA::FactoryPair(&Structure::Allocate<Collection>, &Structure::Convert<Collection>);
|
||||
converters["CollectionChild"] = DNA::FactoryPair(&Structure::Allocate<CollectionChild>, &Structure::Convert<CollectionChild>);
|
||||
converters["CollectionObject"] = DNA::FactoryPair(&Structure::Allocate<CollectionObject>, &Structure::Convert<CollectionObject>);
|
||||
}
|
||||
|
||||
#endif // ASSIMP_BUILD_NO_BLEND_IMPORTER
|
||||
|
|
|
@ -107,6 +107,7 @@ namespace Blender {
|
|||
struct Object;
|
||||
struct MTex;
|
||||
struct Image;
|
||||
struct Collection;
|
||||
|
||||
#include <memory>
|
||||
|
||||
|
@ -147,6 +148,26 @@ struct Group : ElemBase {
|
|||
std::shared_ptr<GroupObject> gobject;
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
struct CollectionObject : ElemBase {
|
||||
//CollectionObject* prev;
|
||||
std::shared_ptr<CollectionObject> next;
|
||||
Object *ob;
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
struct CollectionChild : ElemBase {
|
||||
std::shared_ptr<CollectionChild> next, prev;
|
||||
std::shared_ptr<Collection> 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<Object> camera WARN;
|
||||
std::shared_ptr<World> world WARN;
|
||||
std::shared_ptr<Base> basact WARN;
|
||||
std::shared_ptr<Collection> master_collection WARN;
|
||||
|
||||
ListBase base;
|
||||
|
||||
Scene() :
|
||||
ElemBase(), camera(), world(), basact() {
|
||||
ElemBase(), camera(), world(), basact(), master_collection() {
|
||||
// empty
|
||||
}
|
||||
};
|
||||
|
|
|
@ -62,6 +62,12 @@ template <> void Structure :: Convert<Group> (
|
|||
) const
|
||||
;
|
||||
|
||||
template <> void Structure::Convert<Collection>(
|
||||
Collection& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<MTex> (
|
||||
MTex& dest,
|
||||
const FileDatabase& db
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 3.4 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -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.
|
Binary file not shown.
Binary file not shown.
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue