Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGaia Clary <gaia.clary@machinimatrix.org>2012-08-12 21:13:07 +0400
committerGaia Clary <gaia.clary@machinimatrix.org>2012-08-12 21:13:07 +0400
commit10004d4a421b03f0cdf666b72b4cbadc216030e1 (patch)
tree7b38dc0abb454f96dc39c7095532b4a574292459
parent3ebbfe2c406955ed765a697825cde0c891e83a24 (diff)
fixed: [#32240] Collada import when nodes share geometry but not material
-rw-r--r--source/blender/collada/DocumentImporter.cpp4
-rw-r--r--source/blender/collada/EffectExporter.cpp18
-rw-r--r--source/blender/collada/GeometryExporter.cpp7
-rw-r--r--source/blender/collada/InstanceWriter.cpp10
-rw-r--r--source/blender/collada/MaterialExporter.h11
-rw-r--r--source/blender/collada/MeshImporter.cpp185
-rw-r--r--source/blender/collada/MeshImporter.h19
-rw-r--r--source/blender/collada/collada_utils.cpp5
-rw-r--r--source/blender/collada/collada_utils.h1
9 files changed, 204 insertions, 56 deletions
diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp
index 7cfce9d2526..60b03a211ba 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);
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 d30f9b86a5a..29ffcf53ee9 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 8ee30f691ee..5593fe993f4 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"
@@ -988,6 +988,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,
@@ -1003,21 +1136,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();
@@ -1101,9 +1229,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 e4c1aca395a..2cac26d5329 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
@@ -85,6 +85,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 {
@@ -140,7 +141,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);
@@ -152,7 +155,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);