diff options
author | Campbell Barton <ideasman42@gmail.com> | 2012-08-19 15:01:31 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2012-08-19 15:01:31 +0400 |
commit | 19885babaf8b6e8197a8a63ee239ed85c208bef9 (patch) | |
tree | ea3b576170207e7bbbbfaf650779cd3bb5920e11 /source/blender/collada | |
parent | 78f393f0c3789221603cde786b66b04bcf164594 (diff) | |
parent | 27a8487070b37e6243608571b623e0c5fa279ced (diff) |
svn merge ^/trunk/blender -r49800:49900
Diffstat (limited to 'source/blender/collada')
-rw-r--r-- | source/blender/collada/ArmatureExporter.cpp | 2 | ||||
-rw-r--r-- | source/blender/collada/DocumentImporter.cpp | 4 | ||||
-rw-r--r-- | source/blender/collada/EffectExporter.cpp | 18 | ||||
-rw-r--r-- | source/blender/collada/GeometryExporter.cpp | 7 | ||||
-rw-r--r-- | source/blender/collada/InstanceWriter.cpp | 10 | ||||
-rw-r--r-- | source/blender/collada/MaterialExporter.h | 11 | ||||
-rw-r--r-- | source/blender/collada/MeshImporter.cpp | 190 | ||||
-rw-r--r-- | source/blender/collada/MeshImporter.h | 19 | ||||
-rw-r--r-- | source/blender/collada/collada_utils.cpp | 5 | ||||
-rw-r--r-- | source/blender/collada/collada_utils.h | 1 |
10 files changed, 208 insertions, 59 deletions
diff --git a/source/blender/collada/ArmatureExporter.cpp b/source/blender/collada/ArmatureExporter.cpp index 4ad31bb6cb4..765b09c92d3 100644 --- a/source/blender/collada/ArmatureExporter.cpp +++ b/source/blender/collada/ArmatureExporter.cpp @@ -183,7 +183,7 @@ void ArmatureExporter::add_bone_node(Bone *bone, Object *ob_arm, Scene *sce, #if 0 if (bone->childbase.first == NULL || BLI_countlist(&(bone->childbase)) >= 2) { - add_blender_leaf_bone( bone, ob_arm , node ); + add_blender_leaf_bone( bone, ob_arm, node); } else{ #endif diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp index f7c835c6ce5..1b98d9d6353 100644 --- a/source/blender/collada/DocumentImporter.cpp +++ b/source/blender/collada/DocumentImporter.cpp @@ -208,6 +208,10 @@ void DocumentImporter::finish() write_node(roots[i], NULL, sce, NULL, false); } } + + + mesh_importer.optimize_material_assignements(); + armature_importer.set_tags_map(this->uid_tags_map); armature_importer.make_armatures(mContext); armature_importer.make_shape_keys(); diff --git a/source/blender/collada/EffectExporter.cpp b/source/blender/collada/EffectExporter.cpp index 1eee797b51c..2d9ccc3e3ef 100644 --- a/source/blender/collada/EffectExporter.cpp +++ b/source/blender/collada/EffectExporter.cpp @@ -35,17 +35,19 @@ #include "DocumentExporter.h" #include "MaterialExporter.h" -#include "DNA_mesh_types.h" -#include "DNA_texture_types.h" -#include "DNA_world_types.h" - -#include "BKE_customdata.h" -#include "BKE_mesh.h" -#include "BKE_material.h" - #include "collada_internal.h" #include "collada_utils.h" +extern "C" { + #include "DNA_mesh_types.h" + #include "DNA_texture_types.h" + #include "DNA_world_types.h" + + #include "BKE_customdata.h" + #include "BKE_mesh.h" + #include "BKE_material.h" +} + // OB_MESH is assumed static std::string getActiveUVLayerName(Object *ob) { diff --git a/source/blender/collada/GeometryExporter.cpp b/source/blender/collada/GeometryExporter.cpp index 21c1b56d7b3..06259d71af2 100644 --- a/source/blender/collada/GeometryExporter.cpp +++ b/source/blender/collada/GeometryExporter.cpp @@ -42,12 +42,11 @@ extern "C" { #include "BKE_main.h" #include "BKE_global.h" #include "BKE_library.h" + #include "BKE_customdata.h" + #include "BKE_material.h" + #include "BKE_mesh.h" } - -#include "BKE_customdata.h" -#include "BKE_material.h" -#include "BKE_mesh.h" #include "collada_internal.h" #include "collada_utils.h" diff --git a/source/blender/collada/InstanceWriter.cpp b/source/blender/collada/InstanceWriter.cpp index 5908037d782..be45d5295e5 100644 --- a/source/blender/collada/InstanceWriter.cpp +++ b/source/blender/collada/InstanceWriter.cpp @@ -31,13 +31,13 @@ #include "COLLADASWInstanceMaterial.h" -#include "BKE_customdata.h" -#include "BKE_material.h" - -#include "DNA_mesh_types.h" +extern "C" { + #include "BKE_customdata.h" + #include "BKE_material.h" + #include "DNA_mesh_types.h" +} #include "InstanceWriter.h" - #include "collada_internal.h" #include "collada_utils.h" diff --git a/source/blender/collada/MaterialExporter.h b/source/blender/collada/MaterialExporter.h index f65c8849c84..09d10846b53 100644 --- a/source/blender/collada/MaterialExporter.h +++ b/source/blender/collada/MaterialExporter.h @@ -34,11 +34,12 @@ #include "COLLADASWLibraryMaterials.h" #include "COLLADASWStreamWriter.h" -#include "BKE_material.h" - -#include "DNA_material_types.h" -#include "DNA_object_types.h" -#include "DNA_scene_types.h" +extern "C" { + #include "BKE_material.h" + #include "DNA_material_types.h" + #include "DNA_object_types.h" + #include "DNA_scene_types.h" +} #include "GeometryExporter.h" #include "collada_internal.h" diff --git a/source/blender/collada/MeshImporter.cpp b/source/blender/collada/MeshImporter.cpp index 72926c050bb..b9a4c092552 100644 --- a/source/blender/collada/MeshImporter.cpp +++ b/source/blender/collada/MeshImporter.cpp @@ -39,22 +39,22 @@ #include "COLLADAFWPolygons.h" extern "C" { -#include "BKE_blender.h" -#include "BKE_customdata.h" -#include "BKE_displist.h" -#include "BKE_global.h" -#include "BKE_library.h" -#include "BKE_main.h" -#include "BKE_material.h" -#include "BKE_mesh.h" -#include "BKE_object.h" - -#include "BLI_listbase.h" -#include "BLI_math.h" -#include "BLI_string.h" -#include "BLI_edgehash.h" - -#include "MEM_guardedalloc.h" + #include "BKE_blender.h" + #include "BKE_customdata.h" + #include "BKE_displist.h" + #include "BKE_global.h" + #include "BKE_library.h" + #include "BKE_main.h" + #include "BKE_material.h" + #include "BKE_mesh.h" + #include "BKE_object.h" + + #include "BLI_listbase.h" + #include "BLI_math.h" + #include "BLI_string.h" + #include "BLI_edgehash.h" + + #include "MEM_guardedalloc.h" } #include "ArmatureImporter.h" @@ -467,12 +467,13 @@ bool MeshImporter::primitive_has_faces(COLLADAFW::MeshPrimitive *mp) { } // ================================================================= -// Return the number of faces by summing up +// Return the number of faces by summing up // the facecounts of the parts. // hint: This is done because mesh->getFacesCount() does // count loose edges as extra faces, which is not what we want here. // ================================================================= -void MeshImporter::allocate_face_data(COLLADAFW::Mesh *mesh, Mesh *me, int new_tris) { +void MeshImporter::allocate_face_data(COLLADAFW::Mesh *mesh, Mesh *me, int new_tris) +{ COLLADAFW::MeshPrimitiveArray& prim_arr = mesh->getMeshPrimitives(); int total_facecount = 0; @@ -994,6 +995,139 @@ MTex *MeshImporter::assign_textures_to_uvlayer(COLLADAFW::TextureCoordinateBindi return color_texture; } +/** + * this function checks if both objects have the same + * materials assigned to Object (in the same order) + * returns true if condition matches, otherwise false; + **/ +static bool bc_has_same_material_configuration(Object *ob1, Object *ob2) +{ + if (ob1->totcol != ob2->totcol) return false; // not same number of materials + if (ob1->totcol == 0) return false; // no material at all + + for(int index=0; index < ob1->totcol; index++) { + if (ob1->matbits[index] != ob2->matbits[index]) return false; // shouldn't happen + if (ob1->matbits[index] == 0) return false; // shouldn't happen + if (ob1->mat[index] != ob2->mat[index]) return false; // different material assignment + } + return true; +} + + +/** + * + * Caution here: This code assumes tha all materials are assigned to Object + * and no material is assigned to Data. + * That is true right after the objects have been imported. + * + **/ +static void bc_copy_materials_to_data(Object *ob, Mesh *me) +{ + for (int index = 0; index < ob->totcol; index++) { + ob->matbits[index] = 0; + me->mat[index] = ob->mat[index]; + } +} + +/** + * + * Remove all references to materials from the object + * + **/ +static void bc_remove_materials_from_object(Object *ob, Mesh *me) +{ + for (int index = 0; index < ob->totcol; index++) { + ob->matbits[index] = 0; + ob->mat[index] = NULL; + } +} + +/** + * Returns the list of Users of the given Mesh object. + * Note: This function uses the object user flag to control + * which objects have already been processed. + **/ +std::vector<Object *> MeshImporter::get_all_users_of(Mesh *reference_mesh) +{ + std::vector<Object *> mesh_users; + for (std::vector<Object *>::iterator it = imported_objects.begin(); + it != imported_objects.end(); ++it) + { + Object *ob = (*it); + if (bc_is_marked(ob)) { + bc_remove_mark(ob); + Mesh *me = (Mesh *) ob->data; + if (me == reference_mesh) + mesh_users.push_back(ob); + } + } + return mesh_users; +} + +/** + * + * During import all materials have been assigned to Object. + * Now we iterate over the imported objects and optimize + * the assignements as follows: + * + * for each imported geometry: + * if number of users is 1: + * get the user (object) + * move the materials from Object to Data + * else: + * determine which materials are assigned to the first user + * check if all other users have the same materials in the same order + * if the check is positive: + * Add the materials of the first user to the geometry + * adjust all other users accordingly. + * + **/ +void MeshImporter::optimize_material_assignements() +{ + for (std::vector<Object *>::iterator it = imported_objects.begin(); + it != imported_objects.end(); ++it) + { + Object *ob = (*it); + Mesh *me = (Mesh *) ob->data; + if (me->id.us==1) { + bc_copy_materials_to_data(ob,me); + bc_remove_materials_from_object(ob,me); + bc_remove_mark(ob); + } + else if (me->id.us > 1) + { + bool can_move = true; + std::vector<Object *> mesh_users = get_all_users_of(me); + if (mesh_users.size() > 1) + { + Object *ref_ob = mesh_users[0]; + for (int index = 1; index < mesh_users.size(); index++) { + if (!bc_has_same_material_configuration(ref_ob, mesh_users[index])) { + can_move = false; + break; + } + } + if (can_move) { + bc_copy_materials_to_data(ref_ob,me); + for (int index = 0; index < mesh_users.size(); index++) { + Object *object = mesh_users[index]; + bc_remove_materials_from_object(object,me); + bc_remove_mark(object); + } + } + } + } + } +} + +/** + * We do not know in advance which objects will share geometries. + * And we do not know either if the objects which share geometries + * come along with different materials. So we first create the objects + * and assign the materials to Object, then in a later cleanup we decide + * which materials shall be moved to the created geometries. Also see + * optimize_material_assignements() above. + */ MTFace *MeshImporter::assign_material_to_geom(COLLADAFW::MaterialBinding cmaterial, std::map<COLLADAFW::UniqueId, Material *>& uid_material_map, Object *ob, const COLLADAFW::UniqueId *geom_uid, @@ -1009,21 +1143,16 @@ MTFace *MeshImporter::assign_material_to_geom(COLLADAFW::MaterialBinding cmateri fprintf(stderr, "Cannot find material by UID.\n"); return NULL; } - - // different nodes can point to same geometry, but still also specify the same materials - // again. Make sure we don't overwrite them on the next occurrences, so keep list of - // what we already have handled. - std::multimap<COLLADAFW::UniqueId, COLLADAFW::UniqueId>::iterator it; - it = materials_mapped_to_geom.find(*geom_uid); - while (it != materials_mapped_to_geom.end()) { - if (it->second == ma_uid && it->first == *geom_uid) return NULL; // do nothing if already found - it++; - } + // first time we get geom_uid, ma_uid pair. Save for later check. materials_mapped_to_geom.insert(std::pair<COLLADAFW::UniqueId, COLLADAFW::UniqueId>(*geom_uid, ma_uid)); Material *ma = uid_material_map[ma_uid]; - assign_material(ob, ma, ob->totcol + 1); + + // Attention! This temporaly assigns material to object on purpose! + // See note above. + ob->actcol=0; + assign_material(ob, ma, mat_index + 1, BKE_MAT_ASSIGN_OBJECT); COLLADAFW::TextureCoordinateBindingArray& tex_array = cmaterial.getTextureCoordinateBindingArray(); @@ -1107,9 +1236,12 @@ Object *MeshImporter::create_mesh_object(COLLADAFW::Node *node, COLLADAFW::Insta // add object Object *ob = bc_add_object(scene, OB_MESH, name); + bc_set_mark(ob); // used later for material assignement optimization + // store object pointer for ArmatureImporter uid_object_map[*geom_uid] = ob; + imported_objects.push_back(ob); // replace ob->data freeing the old one Mesh *old_mesh = (Mesh *)ob->data; diff --git a/source/blender/collada/MeshImporter.h b/source/blender/collada/MeshImporter.h index b420ef2d664..946f9ff99e3 100644 --- a/source/blender/collada/MeshImporter.h +++ b/source/blender/collada/MeshImporter.h @@ -40,6 +40,11 @@ #include "COLLADAFWTypes.h" #include "COLLADAFWUniqueId.h" +#include "ArmatureImporter.h" +#include "collada_utils.h" + +extern "C" { +#include "BLI_edgehash.h" #include "DNA_material_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" @@ -47,11 +52,6 @@ #include "DNA_scene_types.h" #include "DNA_texture_types.h" -#include "ArmatureImporter.h" -#include "collada_utils.h" - -extern "C" { -#include "BLI_edgehash.h" } // only for ArmatureImporter to "see" MeshImporter::get_object_by_geom_uid @@ -86,6 +86,7 @@ private: std::map<COLLADAFW::UniqueId, Mesh*> uid_mesh_map; // geometry unique id-to-mesh map std::map<COLLADAFW::UniqueId, Object*> uid_object_map; // geom uid-to-object + std::vector<Object*> imported_objects; // list of imported objects // this structure is used to assign material indices to faces // it holds a portion of Mesh faces and corresponds to a DAE primitive list (<triangles>, <polylist>, etc.) struct Primitive { @@ -141,7 +142,9 @@ private: void get_vector(float v[3], COLLADAFW::MeshVertexData& arr, int i, int stride); bool flat_face(unsigned int *nind, COLLADAFW::MeshVertexData& nor, int count); - + + std::vector<Object *> get_all_users_of(Mesh *reference_mesh); + public: MeshImporter(UnitConverter *unitconv, ArmatureImporter *arm, Scene *sce); @@ -155,7 +158,9 @@ public: MTex *assign_textures_to_uvlayer(COLLADAFW::TextureCoordinateBinding &ctexture, Mesh *me, TexIndexTextureArrayMap& texindex_texarray_map, MTex *color_texture); - + + void optimize_material_assignements(); + MTFace *assign_material_to_geom(COLLADAFW::MaterialBinding cmaterial, std::map<COLLADAFW::UniqueId, Material*>& uid_material_map, Object *ob, const COLLADAFW::UniqueId *geom_uid, diff --git a/source/blender/collada/collada_utils.cpp b/source/blender/collada/collada_utils.cpp index 955d699d96c..018d66c6f55 100644 --- a/source/blender/collada/collada_utils.cpp +++ b/source/blender/collada/collada_utils.cpp @@ -230,6 +230,11 @@ void bc_remove_mark(Object *ob) ob->id.flag &= ~LIB_DOIT; } +void bc_set_mark(Object *ob) +{ + ob->id.flag |= LIB_DOIT; +} + // Use bubble sort algorithm for sorting the export set void bc_bubble_sort_by_Object_name(LinkNode *export_set) { diff --git a/source/blender/collada/collada_utils.h b/source/blender/collada/collada_utils.h index 5f72581f584..b52115722fe 100644 --- a/source/blender/collada/collada_utils.h +++ b/source/blender/collada/collada_utils.h @@ -67,6 +67,7 @@ extern bool bc_has_object_type(LinkNode *export_set, short obtype); extern int bc_is_marked(Object *ob); extern void bc_remove_mark(Object *ob); +extern void bc_set_mark(Object *ob); extern char *bc_CustomData_get_layer_name(const CustomData *data, int type, int n); extern char *bc_CustomData_get_active_layer_name(const CustomData *data, int type); |