collada: export UV Textures as materials. Note: the reimport of the exported collada...
authorGaia Clary <gaia.clary@machinimatrix.org>
Sat, 24 Jun 2017 20:16:32 +0000 (22:16 +0200)
committerGaia Clary <gaia.clary@machinimatrix.org>
Sat, 24 Jun 2017 20:16:47 +0000 (22:16 +0200)
source/blender/collada/DocumentExporter.cpp
source/blender/collada/EffectExporter.cpp
source/blender/collada/EffectExporter.h
source/blender/collada/GeometryExporter.cpp
source/blender/collada/ImageExporter.cpp
source/blender/collada/InstanceWriter.cpp
source/blender/collada/InstanceWriter.h
source/blender/collada/MaterialExporter.cpp

index bd32e989ae368fe5a319c7bff5d77209f1bb7005..634071bc90f57a5ac054630beba6771724451ca6 100644 (file)
@@ -138,7 +138,8 @@ extern bool bc_has_object_type(LinkNode *export_set, short obtype);
 char *bc_CustomData_get_layer_name(const struct CustomData *data, int type, int n)
 {
        int layer_index = CustomData_get_layer_index(data, type);
-       if (layer_index < 0) return NULL;
+       if (layer_index < 0)
+               return NULL;
 
        return data->layers[layer_index + n].name;
 }
@@ -147,9 +148,10 @@ char *bc_CustomData_get_active_layer_name(const CustomData *data, int type)
 {
        /* get the layer index of the active layer of type */
        int layer_index = CustomData_get_active_layer_index(data, type);
-       if (layer_index < 0) return NULL;
+       if (layer_index < 1)
+               return NULL;
 
-       return data->layers[layer_index].name;
+       return bc_CustomData_get_layer_name(data, type, layer_index-1);
 }
 
 DocumentExporter::DocumentExporter(const ExportSettings *export_settings) : export_settings(export_settings) {
index 4ce88d96888185373247ae43e04c485f38fd7ddd..e0c81cfc54bd4059882d9acc39bb67e4806437b2 100644 (file)
@@ -27,7 +27,6 @@
 
 
 #include <map>
-#include <set>
 
 #include "COLLADASWEffectProfile.h"
 #include "COLLADAFWColorOrTexture.h"
@@ -49,21 +48,10 @@ extern "C" {
        #include "BKE_material.h"
 }
 
-// OB_MESH is assumed
-static std::string getActiveUVLayerName(Object *ob)
-{
-       Mesh *me = (Mesh *)ob->data;
-
-       int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
-       if (num_layers)
-               return std::string(bc_CustomData_get_active_layer_name(&me->fdata, CD_MTFACE));
-               
-       return "";
-}
-
 EffectsExporter::EffectsExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings) : COLLADASW::LibraryEffects(sw), export_settings(export_settings) {
 }
 
+
 bool EffectsExporter::hasEffects(Scene *sce)
 {
        Base *base = (Base *)sce->base.first;
@@ -86,13 +74,49 @@ bool EffectsExporter::hasEffects(Scene *sce)
 
 void EffectsExporter::exportEffects(Scene *sce)
 {
-       if (hasEffects(sce)) {
-               this->scene = sce;
-               openLibrary();
-               MaterialFunctor mf;
-               mf.forEachMaterialInExportSet<EffectsExporter>(sce, *this, this->export_settings->export_set);
-
-               closeLibrary();
+       this->scene = sce;
+       
+       if (this->export_settings->export_texture_type == BC_TEXTURE_TYPE_MAT) {
+               if (hasEffects(sce)) {
+                               MaterialFunctor mf;
+                               openLibrary();
+                               mf.forEachMaterialInExportSet<EffectsExporter>(sce, *this, this->export_settings->export_set);
+                               closeLibrary();
+               }
+       }
+       else if (this->export_settings->export_texture_type == BC_TEXTURE_TYPE_UV) {
+               std::set<Object *> uv_textured_obs = bc_getUVTexturedObjects(sce, !this->export_settings->active_uv_only);
+               std::set<Image *> uv_images = bc_getUVImages(sce, !this->export_settings->active_uv_only);
+               if (uv_images.size() > 0) {
+                       openLibrary();
+                       std::set<Image *>::iterator uv_images_iter;
+                       for (uv_images_iter = uv_images.begin();
+                               uv_images_iter != uv_images.end();
+                               uv_images_iter++) {
+
+                               Image *ima = *uv_images_iter;
+                               std::string key(id_name(ima));
+                               key = translate_id(key);
+                               COLLADASW::Sampler sampler(COLLADASW::Sampler::SAMPLER_TYPE_2D,
+                                       key + COLLADASW::Sampler::SAMPLER_SID_SUFFIX,
+                                       key + COLLADASW::Sampler::SURFACE_SID_SUFFIX);
+                               sampler.setImageId(key);
+
+                               openEffect(key + "-effect");
+                               COLLADASW::EffectProfile ep(mSW);
+                               ep.setProfileType(COLLADASW::EffectProfile::COMMON);
+                               ep.setShaderType(COLLADASW::EffectProfile::PHONG);
+                               ep.setDiffuse(createTexture(ima, key, &sampler), false, "diffuse");
+                               COLLADASW::ColorOrTexture cot = getcol(0, 0, 0, 1.0f);
+                               ep.setSpecular(cot, false, "specular");
+                               ep.openProfile();
+                               ep.addProfileElements();
+                               ep.addExtraTechniques(mSW);
+                               ep.closeProfile();
+                               closeEffect();
+                       }
+                       closeLibrary();
+               }
        }
 }
 
@@ -172,6 +196,18 @@ void EffectsExporter::writeTextures(COLLADASW::EffectProfile &ep,
        }
 }
 
+void EffectsExporter::exportUVMats(Object *ob)
+{
+       std::vector<int> tex_indices;
+       int active_uv_layer = -1;
+       std::set<Image *> uv_textures;
+       if (ob->type == OB_MESH && ob->totcol && this->export_settings->export_texture_type == BC_TEXTURE_TYPE_UV) {
+               bool active_uv_only = this->export_settings->active_uv_only;
+               Mesh *me = (Mesh *)ob->data;
+               active_uv_layer = CustomData_get_active_layer_index(&me->pdata, CD_MTEXPOLY);
+       }
+}
+
 void EffectsExporter::operator()(Material *ma, Object *ob)
 {
        // create a list of indices to textures of type TEX_IMAGE
@@ -365,7 +401,7 @@ void EffectsExporter::operator()(Material *ma, Object *ob)
 
        // used as fallback when MTex->uvname is "" (this is pretty common)
        // it is indeed the correct value to use in that case
-       std::string active_uv(getActiveUVLayerName(ob));
+       std::string active_uv(bc_get_active_uvlayer_name(ob));
 
        // write textures
        // XXX very slow
@@ -385,16 +421,18 @@ void EffectsExporter::operator()(Material *ma, Object *ob)
                writeTextures(ep, key, sampler, t, ima, uvname);
        }
 
-       std::set<Image *>::iterator uv_t_iter;
-       int idx;
-       for (idx = 0, uv_t_iter = uv_textures.begin(); uv_t_iter != uv_textures.end(); uv_t_iter++, idx++ ) {
-               if (active_uv_layer>-1 && idx==active_uv_layer) {
+       if (active_uv_layer > -1) {
+               // Export only UV textures assigned to active UV Layer (sounds reasonable, but is that correct?)
+               std::set<Image *>::iterator uv_t_iter;
+
+               for (uv_t_iter = uv_textures.begin(); uv_t_iter != uv_textures.end(); uv_t_iter++) {
                        Image *ima = *uv_t_iter;
                        std::string key(id_name(ima));
                        key = translate_id(key);
                        int i = im_samp_map[key];
                        COLLADASW::Sampler *sampler = (COLLADASW::Sampler *)samp_surf[i];
                        ep.setDiffuse(createTexture(ima, active_uv, sampler), false, "diffuse");
+                       ep.setShaderType(COLLADASW::EffectProfile::PHONG);
                }
        }
 
index d20cbfdfe0b41a397b9d9d6242d85b867c276d32..b11699b56e20da35e147d00e6096c7a9cf2457ea 100644 (file)
@@ -47,6 +47,8 @@ class EffectsExporter: COLLADASW::LibraryEffects
 {
 public:
        EffectsExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings);
+       void EffectsExporter::exportUVMats(Object *ob);
+
        void exportEffects(Scene *sce);
 
        void operator()(Material *ma, Object *ob);
index 2ba0ccc827cac98df367874364896024f14757ef..db3b8a62c335b5a92847e08205160ad1b4b30256 100644 (file)
@@ -135,13 +135,15 @@ void GeometryExporter::operator()(Object *ob)
        // Only create Polylists if number of faces > 0
        if (me->totface > 0) {
                // XXX slow
-               if (ob->totcol) {
+               if (ob->totcol && this->export_settings->export_texture_type == BC_TEXTURE_TYPE_MAT) {
                        for (int a = 0; a < ob->totcol; a++) {
                                createPolylist(a, has_uvs, has_color, ob, me, geom_id, norind);
                        }
                }
                else {
-                       createPolylist(0, has_uvs, has_color, ob, me, geom_id, norind);
+                       bool all_uv_layers = !this->export_settings->active_uv_only;
+                       std::set<Image *> uv_images = bc_getUVImages(ob, all_uv_layers);
+                       createPolylists(uv_images, has_uvs, has_color, ob, me, geom_id, norind);
                }
        }
        
@@ -221,13 +223,15 @@ void GeometryExporter::export_key_mesh(Object *ob, Mesh *me, KeyBlock *kb)
        //createLooseEdgeList(ob, me, geom_id, norind);
 
        // XXX slow             
-       if (ob->totcol) {
+       if (ob->totcol && this->export_settings->export_texture_type == BC_TEXTURE_TYPE_MAT) {
                for (int a = 0; a < ob->totcol; a++) {
                        createPolylist(a, has_uvs, has_color, ob, me, geom_id, norind);
                }
        }
        else {
-               createPolylist(0, has_uvs, has_color, ob, me, geom_id, norind);
+               bool all_uv_layers = !this->export_settings->active_uv_only;
+               std::set<Image *> uv_images = bc_getUVImages(ob, all_uv_layers);
+               createPolylists(uv_images, has_uvs, has_color, ob, me, geom_id, norind);
        }
        
        closeMesh();
@@ -296,7 +300,8 @@ std::string GeometryExporter::makeVertexColorSourceId(std::string& geom_id, char
        return result;
 }
 
-// powerful because it handles both cases when there is material and when there's not
+
+// Export meshes with Materials
 void GeometryExporter::createPolylist(short material_index,
                                       bool has_uvs,
                                       bool has_color,
@@ -361,13 +366,21 @@ void GeometryExporter::createPolylist(short material_index,
        int active_uv_index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE)-1;
        for (i = 0; i < num_layers; i++) {
                if (!this->export_settings->active_uv_only || i == active_uv_index) {
+                       
+                       std::string uv_name(bc_get_uvlayer_name(me, i));
+                       std::string effective_id = geom_id; // (uv_name == "") ? geom_id : uv_name;
+                       std::string layer_id = makeTexcoordSourceId(
+                               effective_id,
+                               i, this->export_settings->active_uv_only);
 
-                       // char *name = CustomData_get_layer_name(&me->fdata, CD_MTFACE, i);
+                       /* Note: the third parameter denotes the offset of TEXCOORD in polylist elements
+                          For now this is always 2 (This may change sometime/maybe) 
+                       */
                        COLLADASW::Input input3(COLLADASW::InputSemantic::TEXCOORD,
-                                                                       makeUrl(makeTexcoordSourceId(geom_id, i, this->export_settings->active_uv_only)),
-                                                                       2, // this is only until we have optimized UV sets
-                                                                       (this->export_settings->active_uv_only) ? 0 : i  // only_active_uv exported -> we have only one set
-                                                                       );
+                               makeUrl(layer_id),
+                               2, // this is only until we have optimized UV sets
+                               (this->export_settings->active_uv_only) ? 0 : i  // only_active_uv exported -> we have only one set
+                               );
                        til.push_back(input3);
                }
        }
@@ -697,7 +710,13 @@ void GeometryExporter::createTexcoordsSource(std::string geom_id, Mesh *me)
                        MLoopUV *mloops = (MLoopUV *)CustomData_get_layer_n(&me->ldata, CD_MLOOPUV, a);
                        
                        COLLADASW::FloatSourceF source(mSW);
-                       std::string layer_id = makeTexcoordSourceId(geom_id, a, this->export_settings->active_uv_only);
+                       std::string active_uv_name(bc_get_active_uvlayer_name(me));
+                       std::string effective_id = geom_id; // (active_uv_name == "") ? geom_id : active_uv_name;
+                       std::string layer_id = makeTexcoordSourceId(
+                               effective_id, 
+                               a, 
+                               this->export_settings->active_uv_only );
+
                        source.setId(layer_id);
                        source.setArrayId(layer_id + ARRAY_ID_SUFFIX);
                        
index a5ddd3fb990fc441fe8c212839a5ce7fdf51e499..c982ca6e84374ac1f0ee373cb9e552d34fd176f8 100644 (file)
@@ -55,9 +55,9 @@ ImagesExporter::ImagesExporter(COLLADASW::StreamWriter *sw, const ExportSettings
 
 void ImagesExporter::export_UV_Image(Image *image, bool use_copies) 
 {
-       std::string name(id_name(image));
-       std::string translated_name(translate_id(name));
-       bool not_yet_exported = find(mImages.begin(), mImages.end(), translated_name) == mImages.end();
+       std::string id(id_name(image));
+       std::string translated_id(translate_id(id));
+       bool not_yet_exported = find(mImages.begin(), mImages.end(), translated_id) == mImages.end();
 
        if (not_yet_exported) {
 
@@ -88,7 +88,7 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies)
 
                        // make absolute destination path
 
-                       BLI_strncpy(export_file, name.c_str(), sizeof(export_file));
+                       BLI_strncpy(export_file, id.c_str(), sizeof(export_file));
                        BKE_image_path_ensure_ext_from_imformat(export_file, &imageFormat);
 
                        BLI_join_dirfile(export_path, sizeof(export_path), export_dir, export_file);
@@ -143,10 +143,11 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies)
                        }
                }
 
-               COLLADASW::Image img(COLLADABU::URI(COLLADABU::URI::nativePathToUri(export_path)), translated_name, translated_name); /* set name also to mNameNC. This helps other viewers import files exported from Blender better */
+               /* set name also to mNameNC. This helps other viewers import files exported from Blender better */
+               COLLADASW::Image img(COLLADABU::URI(COLLADABU::URI::nativePathToUri(export_path)), translated_id, translated_id); 
                img.add(mSW);
                fprintf(stdout, "Collada export: Added image: %s\n", export_file);
-               mImages.push_back(translated_name);
+               mImages.push_back(translated_id);
 
                BKE_image_release_ibuf(image, imbuf, NULL);
        }
@@ -161,7 +162,7 @@ void ImagesExporter::export_UV_Images()
 
        for (node = this->export_settings->export_set; node; node = node->next) {
                Object *ob = (Object *)node->link;
-               if (ob->type == OB_MESH && ob->totcol) {
+               if (ob->type == OB_MESH) {
                        Mesh *me     = (Mesh *) ob->data;
                        BKE_mesh_tessface_ensure(me);
                        int active_uv_layer = CustomData_get_active_layer_index(&me->pdata, CD_MTEXPOLY);
@@ -189,7 +190,13 @@ void ImagesExporter::export_UV_Images()
        }
 }
 
-
+/* ============================================================
+ * Check if there are any images to be exported
+ * Returns true as soon as an object is detected that
+ * either has an UV Texture assigned, or has a material
+ * assigned that uses an Image Texture.
+ * ============================================================
+ */
 bool ImagesExporter::hasImages(Scene *sce)
 {
        LinkNode *node;
index 87a38ac6295499e10406358e3661bab3d3e46777..776d9750175c716b08e0a01673989aa8c1480b93 100644 (file)
@@ -43,14 +43,19 @@ extern "C" {
 
 void InstanceWriter::add_material_bindings(COLLADASW::BindMaterial& bind_material, Object *ob, bool active_uv_only, BC_export_texture_type export_texture_type)
 {
-       for (int a = 0; a < ob->totcol; a++) {
-               Material *ma = give_current_material(ob, a + 1);
-                       
-               COLLADASW::InstanceMaterialList& iml = bind_material.getInstanceMaterialList();
+       bool all_uv_layers = !active_uv_only;
+       COLLADASW::InstanceMaterialList& iml = bind_material.getInstanceMaterialList();
 
-               if (ma) {
-                       std::string matid(get_material_id(ma));
-                       matid = translate_id(matid);
+       if (export_texture_type == BC_TEXTURE_TYPE_UV)
+       {
+               std::set<Image *> uv_images = bc_getUVImages(ob, all_uv_layers);
+               std::set<Image *>::iterator uv_images_iter;
+               for (uv_images_iter = uv_images.begin();
+                       uv_images_iter != uv_images.end();
+                       uv_images_iter++) {
+                       Image *ima = *uv_images_iter;
+                       std::string matid(id_name(ima));
+                       matid = get_material_id_from_id(matid);
                        std::ostringstream ostr;
                        ostr << matid;
                        COLLADASW::InstanceMaterial im(ostr.str(), COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, matid));
@@ -71,4 +76,32 @@ void InstanceWriter::add_material_bindings(COLLADASW::BindMaterial& bind_materia
                        iml.push_back(im);
                }
        }
+
+       else if (export_texture_type == BC_TEXTURE_TYPE_MAT) {
+               for (int a = 0; a < ob->totcol; a++) {
+                       Material *ma = give_current_material(ob, a + 1);
+                       if (ma) {
+                               std::string matid(get_material_id(ma));
+                               matid = translate_id(matid);
+                               std::ostringstream ostr;
+                               ostr << matid;
+                               COLLADASW::InstanceMaterial im(ostr.str(), COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, matid));
+
+                               // create <bind_vertex_input> for each uv map
+                               Mesh *me = (Mesh *)ob->data;
+                               int totlayer = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
+
+                               int map_index = 0;
+                               int active_uv_index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE) - 1;
+                               for (int b = 0; b < totlayer; b++) {
+                                       if (!active_uv_only || b == active_uv_index) {
+                                               char *name = bc_CustomData_get_layer_name(&me->fdata, CD_MTFACE, b);
+                                               im.push_back(COLLADASW::BindVertexInput(name, "TEXCOORD", map_index++));
+                                       }
+                               }
+
+                               iml.push_back(im);
+                       }
+               }
+       }
 }
index 49ddf091b1c2e0072866b2366998612fde82da21..a46027325a271797312fe0597929de4c2adb4629 100644 (file)
 #include "COLLADASWBindMaterial.h"
 
 #include "DNA_object_types.h"
+#include "collada.h"
 
 class InstanceWriter
 {
 protected:
-       void add_material_bindings(COLLADASW::BindMaterial& bind_material, Object *ob, bool active_uv_only);
+       void add_material_bindings(COLLADASW::BindMaterial& bind_material, Object *ob, bool active_uv_only, BC_export_texture_type export_texture_type);
 };
 
 #endif
index a91487094fa8be7152abc4c22b2cd3d52022cf4e..94e9b7661e4e33dca32d1b1bca37699a9e8ae0c8 100644 (file)
@@ -49,8 +49,7 @@ void MaterialsExporter::exportMaterials(Scene *sce)
                        closeLibrary();
                }
        }
-#if 0
-       // Temporary discarded (to keep consistent commits)
+
        else if (this->export_settings->export_texture_type == BC_TEXTURE_TYPE_UV)
        {
                std::set<Image *> uv_images = bc_getUVImages(sce, !this->export_settings->active_uv_only);
@@ -72,7 +71,7 @@ void MaterialsExporter::exportMaterials(Scene *sce)
                        closeLibrary();
                }
        }
-#endif
+
 }
 
 bool MaterialsExporter::hasMaterials(Scene *sce)