collada: export UV Textures as materials. Note: the reimport of the exported collada...
[blender.git] / source / blender / collada / GeometryExporter.cpp
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Contributor(s): Chingiz Dyussenov, Arystanbek Dyussenov, Jan Diederich, Tod Liverseed,
19  *                 Nathan Letwory
20  *
21  * ***** END GPL LICENSE BLOCK *****
22  */
23
24 /** \file blender/collada/GeometryExporter.cpp
25  *  \ingroup collada
26  */
27
28
29 #include <sstream>
30
31 #include "COLLADASWPrimitves.h"
32 #include "COLLADASWSource.h"
33 #include "COLLADASWVertices.h"
34 #include "COLLADABUUtils.h"
35
36 #include "GeometryExporter.h"
37
38 #include "DNA_meshdata_types.h"
39
40 extern "C" {
41         #include "BLI_utildefines.h"
42
43         #include "BKE_DerivedMesh.h"
44         #include "BKE_main.h"
45         #include "BKE_global.h"
46         #include "BKE_library.h"
47         #include "BKE_customdata.h"
48         #include "BKE_material.h"
49         #include "BKE_mesh.h"
50 }
51
52 #include "collada_internal.h"
53 #include "collada_utils.h"
54
55
56 // TODO: optimize UV sets by making indexed list with duplicates removed
57 GeometryExporter::GeometryExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings) : COLLADASW::LibraryGeometries(sw), export_settings(export_settings)
58 {
59 }
60
61 void GeometryExporter::exportGeom(Scene *sce)
62 {
63         openLibrary();
64
65         mScene = sce;
66         GeometryFunctor gf;
67         gf.forEachMeshObjectInExportSet<GeometryExporter>(sce, *this, this->export_settings->export_set);
68
69         closeLibrary();
70 }
71
72 void GeometryExporter::operator()(Object *ob)
73
74         // XXX don't use DerivedMesh, Mesh instead?
75 #if 0           
76         DerivedMesh *dm = mesh_get_derived_final(mScene, ob, CD_MASK_BAREMESH);
77 #endif
78
79         bool use_instantiation = this->export_settings->use_object_instantiation;
80         Mesh *me = bc_get_mesh_copy( mScene, 
81                                         ob,
82                                         this->export_settings->export_mesh_type,
83                                         this->export_settings->apply_modifiers,
84                                         this->export_settings->triangulate);
85
86         std::string geom_id = get_geometry_id(ob, use_instantiation);
87         std::vector<Normal> nor;
88         std::vector<BCPolygonNormalsIndices> norind;
89
90         // Skip if linked geometry was already exported from another reference
91         if (use_instantiation && 
92             exportedGeometry.find(geom_id) != exportedGeometry.end())
93         {
94                 return;
95         }
96
97         std::string geom_name = (use_instantiation) ? id_name(ob->data) : id_name(ob);
98
99         exportedGeometry.insert(geom_id);
100
101         bool has_color = (bool)CustomData_has_layer(&me->fdata, CD_MCOL);
102
103         create_normals(nor, norind, me);
104
105         // openMesh(geoId, geoName, meshId)
106         openMesh(geom_id, geom_name);
107         
108         // writes <source> for vertex coords
109         createVertsSource(geom_id, me);
110         
111         // writes <source> for normal coords
112         createNormalsSource(geom_id, me, nor);
113
114         bool has_uvs = (bool)CustomData_has_layer(&me->fdata, CD_MTFACE);
115         
116         // writes <source> for uv coords if mesh has uv coords
117         if (has_uvs) {
118                 createTexcoordsSource(geom_id, me);
119         }
120
121         if (has_color) {
122                 createVertexColorSource(geom_id, me);
123         }
124         // <vertices>
125
126         COLLADASW::Vertices verts(mSW);
127         verts.setId(getIdBySemantics(geom_id, COLLADASW::InputSemantic::VERTEX));
128         COLLADASW::InputList &input_list = verts.getInputList();
129         COLLADASW::Input input(COLLADASW::InputSemantic::POSITION, getUrlBySemantics(geom_id, COLLADASW::InputSemantic::POSITION));
130         input_list.push_back(input);
131         verts.add();
132
133         createLooseEdgeList(ob, me, geom_id);
134
135         // Only create Polylists if number of faces > 0
136         if (me->totface > 0) {
137                 // XXX slow
138                 if (ob->totcol && this->export_settings->export_texture_type == BC_TEXTURE_TYPE_MAT) {
139                         for (int a = 0; a < ob->totcol; a++) {
140                                 createPolylist(a, has_uvs, has_color, ob, me, geom_id, norind);
141                         }
142                 }
143                 else {
144                         bool all_uv_layers = !this->export_settings->active_uv_only;
145                         std::set<Image *> uv_images = bc_getUVImages(ob, all_uv_layers);
146                         createPolylists(uv_images, has_uvs, has_color, ob, me, geom_id, norind);
147                 }
148         }
149         
150         closeMesh();
151         
152         if (me->flag & ME_TWOSIDED) {
153                 mSW->appendTextBlock("<extra><technique profile=\"MAYA\"><double_sided>1</double_sided></technique></extra>");
154         }
155
156         closeGeometry();
157
158         if (this->export_settings->include_shapekeys) {
159                 Key * key = BKE_key_from_object(ob);
160                 if (key) {
161                         KeyBlock * kb = (KeyBlock *)key->block.first;
162                         //skip the basis
163                         kb = kb->next;
164                         for (; kb; kb = kb->next) {
165                                 BKE_keyblock_convert_to_mesh(kb, me);
166                                 export_key_mesh(ob, me, kb);
167                         }
168                 }
169         }
170
171         BKE_libblock_free_us(G.main, me);
172
173 }
174
175 void GeometryExporter::export_key_mesh(Object *ob, Mesh *me, KeyBlock *kb)
176 {
177         std::string geom_id = get_geometry_id(ob, false) + "_morph_" + translate_id(kb->name);
178         std::vector<Normal> nor;
179         std::vector<BCPolygonNormalsIndices> norind;
180         
181         if (exportedGeometry.find(geom_id) != exportedGeometry.end())
182         {
183                 return;
184         }
185
186         std::string geom_name = kb->name;
187
188         exportedGeometry.insert(geom_id);
189
190         bool has_color = (bool)CustomData_has_layer(&me->fdata, CD_MCOL);
191
192         create_normals(nor, norind, me);
193
194         // openMesh(geoId, geoName, meshId)
195         openMesh(geom_id, geom_name);
196         
197         // writes <source> for vertex coords
198         createVertsSource(geom_id, me);
199         
200         // writes <source> for normal coords
201         createNormalsSource(geom_id, me, nor);
202
203         bool has_uvs = (bool)CustomData_has_layer(&me->fdata, CD_MTFACE);
204         
205         // writes <source> for uv coords if mesh has uv coords
206         if (has_uvs) {
207                 createTexcoordsSource(geom_id, me);
208         }
209
210         if (has_color) {
211                 createVertexColorSource(geom_id, me);
212         }
213
214         // <vertices>
215
216         COLLADASW::Vertices verts(mSW);
217         verts.setId(getIdBySemantics(geom_id, COLLADASW::InputSemantic::VERTEX));
218         COLLADASW::InputList &input_list = verts.getInputList();
219         COLLADASW::Input input(COLLADASW::InputSemantic::POSITION, getUrlBySemantics(geom_id, COLLADASW::InputSemantic::POSITION));
220         input_list.push_back(input);
221         verts.add();
222
223         //createLooseEdgeList(ob, me, geom_id, norind);
224
225         // XXX slow             
226         if (ob->totcol && this->export_settings->export_texture_type == BC_TEXTURE_TYPE_MAT) {
227                 for (int a = 0; a < ob->totcol; a++) {
228                         createPolylist(a, has_uvs, has_color, ob, me, geom_id, norind);
229                 }
230         }
231         else {
232                 bool all_uv_layers = !this->export_settings->active_uv_only;
233                 std::set<Image *> uv_images = bc_getUVImages(ob, all_uv_layers);
234                 createPolylists(uv_images, has_uvs, has_color, ob, me, geom_id, norind);
235         }
236         
237         closeMesh();
238         
239         if (me->flag & ME_TWOSIDED) {
240                 mSW->appendTextBlock("<extra><technique profile=\"MAYA\"><double_sided>1</double_sided></technique></extra>");
241         }
242
243         closeGeometry();
244 }
245
246 void GeometryExporter::createLooseEdgeList(Object *ob,
247                                            Mesh   *me,
248                                            std::string& geom_id)
249 {
250
251         MEdge *medges = me->medge;
252         int totedges  = me->totedge;
253         int edges_in_linelist = 0;
254         std::vector<unsigned int> edge_list;
255         int index;
256
257         // Find all loose edges in Mesh 
258         // and save vertex indices in edge_list
259         for (index = 0; index < totedges; index++) 
260         {
261                 MEdge *edge = &medges[index];
262
263                 if (edge->flag & ME_LOOSEEDGE)
264                 {
265                         edges_in_linelist += 1;
266                         edge_list.push_back(edge->v1);
267                         edge_list.push_back(edge->v2);
268                 }
269         }
270
271         if (edges_in_linelist > 0)
272         {
273                 // Create the list of loose edges
274                 COLLADASW::Lines lines(mSW);
275
276                 lines.setCount(edges_in_linelist);
277
278
279                 COLLADASW::InputList &til = lines.getInputList();
280                         
281                 // creates <input> in <lines> for vertices 
282                 COLLADASW::Input input1(COLLADASW::InputSemantic::VERTEX, getUrlBySemantics(geom_id, COLLADASW::InputSemantic::VERTEX), 0);
283                 til.push_back(input1);
284
285                 lines.prepareToAppendValues();
286
287                 for (index = 0; index < edges_in_linelist; index++) 
288                 {
289                         lines.appendValues(edge_list[2 * index + 1]);
290                         lines.appendValues(edge_list[2 * index]);
291                 }
292                 lines.finish();
293         }
294
295 }
296
297 std::string GeometryExporter::makeVertexColorSourceId(std::string& geom_id, char *layer_name)
298 {
299         std::string result = getIdBySemantics(geom_id, COLLADASW::InputSemantic::COLOR) + "-" + layer_name;
300         return result;
301 }
302
303
304 // Export meshes with Materials
305 void GeometryExporter::createPolylist(short material_index,
306                                       bool has_uvs,
307                                       bool has_color,
308                                       Object *ob,
309                                       Mesh *me,
310                                       std::string& geom_id,
311                                       std::vector<BCPolygonNormalsIndices>& norind)
312 {
313
314         MPoly *mpolys = me->mpoly;
315         MLoop *mloops = me->mloop;
316         int totpolys  = me->totpoly;
317
318         // <vcount>
319         int i;
320         int faces_in_polylist = 0;
321         std::vector<unsigned long> vcount_list;
322
323         // count faces with this material
324         for (i = 0; i < totpolys; i++) {
325                 MPoly *p = &mpolys[i];
326                 
327                 if (p->mat_nr == material_index) {
328                         faces_in_polylist++;
329                         vcount_list.push_back(p->totloop);
330                 }
331         }
332
333         // no faces using this material
334         if (faces_in_polylist == 0) {
335                 fprintf(stderr, "%s: material with index %d is not used.\n", id_name(ob).c_str(), material_index);
336                 return;
337         }
338                 
339         Material *ma = ob->totcol ? give_current_material(ob, material_index + 1) : NULL;
340         COLLADASW::Polylist polylist(mSW);
341                 
342         // sets count attribute in <polylist>
343         polylist.setCount(faces_in_polylist);
344                 
345         // sets material name
346         if (ma) {
347                 std::string material_id = get_material_id(ma);
348                 std::ostringstream ostr;
349                 ostr << translate_id(material_id);
350                 polylist.setMaterial(ostr.str());
351         }
352                         
353         COLLADASW::InputList &til = polylist.getInputList();
354                 
355         // creates <input> in <polylist> for vertices 
356         COLLADASW::Input input1(COLLADASW::InputSemantic::VERTEX, getUrlBySemantics(geom_id, COLLADASW::InputSemantic::VERTEX), 0);
357                 
358         // creates <input> in <polylist> for normals
359         COLLADASW::Input input2(COLLADASW::InputSemantic::NORMAL, getUrlBySemantics(geom_id, COLLADASW::InputSemantic::NORMAL), 1);
360                 
361         til.push_back(input1);
362         til.push_back(input2);
363                 
364         // if mesh has uv coords writes <input> for TEXCOORD
365         int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
366         int active_uv_index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE)-1;
367         for (i = 0; i < num_layers; i++) {
368                 if (!this->export_settings->active_uv_only || i == active_uv_index) {
369                         
370                         std::string uv_name(bc_get_uvlayer_name(me, i));
371                         std::string effective_id = geom_id; // (uv_name == "") ? geom_id : uv_name;
372                         std::string layer_id = makeTexcoordSourceId(
373                                 effective_id,
374                                 i, this->export_settings->active_uv_only);
375
376                         /* Note: the third parameter denotes the offset of TEXCOORD in polylist elements
377                            For now this is always 2 (This may change sometime/maybe) 
378                         */
379                         COLLADASW::Input input3(COLLADASW::InputSemantic::TEXCOORD,
380                                 makeUrl(layer_id),
381                                 2, // this is only until we have optimized UV sets
382                                 (this->export_settings->active_uv_only) ? 0 : i  // only_active_uv exported -> we have only one set
383                                 );
384                         til.push_back(input3);
385                 }
386         }
387
388         int totlayer_mcol = CustomData_number_of_layers(&me->ldata, CD_MLOOPCOL);
389         if (totlayer_mcol > 0) {
390                 int map_index = 0;
391
392                 for (int a = 0; a < totlayer_mcol; a++) {
393                         char *layer_name = bc_CustomData_get_layer_name(&me->ldata, CD_MLOOPCOL, a);
394                         COLLADASW::Input input4(COLLADASW::InputSemantic::COLOR,
395                                                 makeUrl(makeVertexColorSourceId(geom_id, layer_name)),
396                                                 (has_uvs) ? 3 : 2,  // all color layers have same index order
397                                                 map_index           // set number equals color map index
398                                                 );
399                         til.push_back(input4);
400                         map_index++;
401                 }
402         }
403                 
404         // sets <vcount>
405         polylist.setVCountList(vcount_list);
406                 
407         // performs the actual writing
408         polylist.prepareToAppendValues();
409         
410         // <p>
411         int texindex = 0;
412         for (i = 0; i < totpolys; i++) {
413                 MPoly *p = &mpolys[i];
414                 int loop_count = p->totloop;
415
416                 if (p->mat_nr == material_index) {
417                         MLoop *l = &mloops[p->loopstart];
418                         BCPolygonNormalsIndices normal_indices = norind[i];
419
420                         for (int j = 0; j < loop_count; j++) {
421                                 polylist.appendValues(l[j].v);
422                                 polylist.appendValues(normal_indices[j]);
423                                 if (has_uvs)
424                                         polylist.appendValues(texindex + j);
425
426                                 if (has_color)
427                                         polylist.appendValues(texindex + j);
428                         }
429                 }
430
431                 texindex += loop_count;
432         }
433                 
434         polylist.finish();
435 }
436
437 void GeometryExporter::createPolylists(std::set<Image *> uv_images,
438         bool has_uvs,
439         bool has_color,
440         Object *ob,
441         Mesh *me,
442         std::string& geom_id,
443         std::vector<BCPolygonNormalsIndices>& norind)
444 {
445         std::set<Image *>::iterator uv_images_iter;
446         for (uv_images_iter = uv_images.begin();
447                 uv_images_iter != uv_images.end();
448                 uv_images_iter++) {
449
450                 Image *ima = *uv_images_iter;
451
452                 createPolylist(ima, has_uvs,
453                         has_color,
454                         ob,
455                         me,
456                         geom_id,
457                         norind);
458         }
459 }
460 // Export Meshes with UV Textures (export as materials, see effectExporter and MaterialExporter)
461 // Important: Image *ima must point to an Image
462 void GeometryExporter::createPolylist(Image *ima,
463         bool has_uvs,
464         bool has_color,
465         Object *ob,
466         Mesh *me,
467         std::string& geom_id,
468         std::vector<BCPolygonNormalsIndices>& norind)
469 {
470
471         std::string imageid(id_name(ima));
472         MPoly *mpolys = me->mpoly;
473         MLoop *mloops = me->mloop;
474         MTexPoly *mtpolys = me->mtpoly;
475
476         int totpolys = me->totpoly;
477
478         // <vcount>
479         int i;
480         int faces_in_polylist = 0;
481         std::vector<unsigned long> vcount_list;
482
483         // count faces with this material
484         for (i = 0; i < totpolys; i++) {
485                 MTexPoly *tp = &mtpolys[i];
486                 MPoly *p = &mpolys[i];
487
488                 std::string tpageid(id_name(tp->tpage));
489                 if (tpageid == imageid) {
490                         faces_in_polylist++;
491                         vcount_list.push_back(p->totloop);
492                 }
493         }
494
495         // no faces using this material
496         if (faces_in_polylist == 0) {
497                 fprintf(stderr, "%s: Image %s is not used.\n", id_name(ob).c_str(), imageid);
498                 return;
499         }
500
501         COLLADASW::Polylist polylist(mSW);
502
503         // sets count attribute in <polylist>
504         polylist.setCount(faces_in_polylist);
505
506         // sets material name
507         std::string material_id = get_material_id_from_id(imageid);
508         std::ostringstream ostr;
509         ostr << translate_id(material_id);
510         polylist.setMaterial(ostr.str());
511
512         COLLADASW::InputList &til = polylist.getInputList();
513
514         // creates <input> in <polylist> for vertices 
515         COLLADASW::Input input1(COLLADASW::InputSemantic::VERTEX, getUrlBySemantics(geom_id, COLLADASW::InputSemantic::VERTEX), 0);
516
517         // creates <input> in <polylist> for normals
518         COLLADASW::Input input2(COLLADASW::InputSemantic::NORMAL, getUrlBySemantics(geom_id, COLLADASW::InputSemantic::NORMAL), 1);
519
520         til.push_back(input1);
521         til.push_back(input2);
522
523         // if mesh has uv coords writes <input> for TEXCOORD
524         int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
525         int active_uv_index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE) - 1;
526         for (i = 0; i < num_layers; i++) {
527                 if (!this->export_settings->active_uv_only || i == active_uv_index) {
528
529                         std::string uv_name(bc_get_uvlayer_name(me, i));
530                         std::string effective_id = geom_id; // (uv_name == "") ? geom_id : uv_name;
531                         std::string layer_id = makeTexcoordSourceId(
532                                 effective_id,
533                                 i, this->export_settings->active_uv_only);
534
535                         /* Note: the third parameter denotes the offset of TEXCOORD in polylist elements
536                         For now this is always 2 (This may change sometime/maybe)
537                         */
538                         COLLADASW::Input input3(COLLADASW::InputSemantic::TEXCOORD,
539                                 makeUrl(layer_id),
540                                 2, // this is only until we have optimized UV sets
541                                 (this->export_settings->active_uv_only) ? 0 : i  // only_active_uv exported -> we have only one set
542                                 );
543                         til.push_back(input3);
544                 }
545         }
546
547         int totlayer_mcol = CustomData_number_of_layers(&me->ldata, CD_MLOOPCOL);
548         if (totlayer_mcol > 0) {
549                 int map_index = 0;
550
551                 for (int a = 0; a < totlayer_mcol; a++) {
552                         char *layer_name = bc_CustomData_get_layer_name(&me->ldata, CD_MLOOPCOL, a);
553                         COLLADASW::Input input4(COLLADASW::InputSemantic::COLOR,
554                                 makeUrl(makeVertexColorSourceId(geom_id, layer_name)),
555                                 (has_uvs) ? 3 : 2,  // all color layers have same index order
556                                 map_index           // set number equals color map index
557                                 );
558                         til.push_back(input4);
559                         map_index++;
560                 }
561         }
562
563         // sets <vcount>
564         polylist.setVCountList(vcount_list);
565
566         // performs the actual writing
567         polylist.prepareToAppendValues();
568
569         // <p>
570         int texindex = 0;
571         for (i = 0; i < totpolys; i++) {
572                 MTexPoly *tp = &mtpolys[i];
573                 MPoly *p = &mpolys[i];
574                 int loop_count = p->totloop;
575                 std::string tpageid(id_name(tp->tpage));
576                 if (tpageid == imageid) {
577                         MLoop *l = &mloops[p->loopstart];
578                         BCPolygonNormalsIndices normal_indices = norind[i];
579
580                         for (int j = 0; j < loop_count; j++) {
581                                 polylist.appendValues(l[j].v);
582                                 polylist.appendValues(normal_indices[j]);
583                                 if (has_uvs)
584                                         polylist.appendValues(texindex + j);
585
586                                 if (has_color)
587                                         polylist.appendValues(texindex + j);
588                         }
589                 }
590
591                 texindex += loop_count;
592         }
593
594         polylist.finish();
595 }
596
597 // creates <source> for positions
598 void GeometryExporter::createVertsSource(std::string geom_id, Mesh *me)
599 {
600 #if 0
601         int totverts = dm->getNumVerts(dm);
602         MVert *verts = dm->getVertArray(dm);
603 #endif
604         int totverts = me->totvert;
605         MVert *verts = me->mvert;
606         
607         COLLADASW::FloatSourceF source(mSW);
608         source.setId(getIdBySemantics(geom_id, COLLADASW::InputSemantic::POSITION));
609         source.setArrayId(getIdBySemantics(geom_id, COLLADASW::InputSemantic::POSITION) +
610                           ARRAY_ID_SUFFIX);
611         source.setAccessorCount(totverts);
612         source.setAccessorStride(3);
613
614         COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
615         param.push_back("X");
616         param.push_back("Y");
617         param.push_back("Z");
618         /* main function, it creates <source id = "">, <float_array id = ""
619          * count = ""> */
620         source.prepareToAppendValues();
621         //appends data to <float_array>
622         int i = 0;
623         for (i = 0; i < totverts; i++) {
624                 source.appendValues(verts[i].co[0], verts[i].co[1], verts[i].co[2]);
625         }
626         
627         source.finish();
628
629 }
630
631
632 void GeometryExporter::createVertexColorSource(std::string geom_id, Mesh *me)
633 {
634         /* Find number of vertex color layers */
635         int totlayer_mcol = CustomData_number_of_layers(&me->ldata, CD_MLOOPCOL);
636         if (totlayer_mcol == 0)
637                 return;
638
639         int map_index = 0;
640         for (int a = 0; a < totlayer_mcol; a++) {
641
642                 map_index++;
643                 MLoopCol *mloopcol = (MLoopCol *)CustomData_get_layer_n(&me->ldata, CD_MLOOPCOL, a);
644
645                 COLLADASW::FloatSourceF source(mSW);
646
647                 char *layer_name = bc_CustomData_get_layer_name(&me->ldata, CD_MLOOPCOL, a);
648                 std::string layer_id = makeVertexColorSourceId(geom_id, layer_name);
649                 source.setId(layer_id);
650
651                 source.setNodeName(layer_name);
652
653                 source.setArrayId(layer_id + ARRAY_ID_SUFFIX);
654                 source.setAccessorCount(me->totloop);
655                 source.setAccessorStride(3);
656
657                 COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
658                 param.push_back("R");
659                 param.push_back("G");
660                 param.push_back("B");
661
662                 source.prepareToAppendValues();
663
664                 MPoly *mpoly;
665                 int i;
666                 for (i = 0, mpoly = me->mpoly; i < me->totpoly; i++, mpoly++) {
667                         MLoopCol *mlc = mloopcol + mpoly->loopstart;
668                         for (int j = 0; j < mpoly->totloop; j++, mlc++) {
669                                 source.appendValues(
670                                                 mlc->r / 255.0f,
671                                                 mlc->g / 255.0f,
672                                                 mlc->b / 255.0f
673                                 );
674                         }
675                 }
676         
677                 source.finish();
678         }
679 }
680
681
682 std::string GeometryExporter::makeTexcoordSourceId(std::string& geom_id, int layer_index, bool is_single_layer)
683 {
684         char suffix[20];
685         if (is_single_layer) {
686                 suffix[0] = '\0';
687         }
688         else {
689                 sprintf(suffix, "-%d", layer_index);
690         }
691         return getIdBySemantics(geom_id, COLLADASW::InputSemantic::TEXCOORD) + suffix;
692 }
693
694 //creates <source> for texcoords
695 void GeometryExporter::createTexcoordsSource(std::string geom_id, Mesh *me)
696 {
697
698         int totpoly   = me->totpoly;
699         int totuv     = me->totloop;
700         MPoly *mpolys = me->mpoly;
701
702         int num_layers = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV);
703
704         // write <source> for each layer
705         // each <source> will get id like meshName + "map-channel-1"
706         int active_uv_index = CustomData_get_active_layer_index(&me->ldata, CD_MLOOPUV);
707         for (int a = 0; a < num_layers; a++) {
708                 int layer_index = CustomData_get_layer_index_n(&me->ldata, CD_MLOOPUV, a);
709                 if (!this->export_settings->active_uv_only || layer_index == active_uv_index) {
710                         MLoopUV *mloops = (MLoopUV *)CustomData_get_layer_n(&me->ldata, CD_MLOOPUV, a);
711                         
712                         COLLADASW::FloatSourceF source(mSW);
713                         std::string active_uv_name(bc_get_active_uvlayer_name(me));
714                         std::string effective_id = geom_id; // (active_uv_name == "") ? geom_id : active_uv_name;
715                         std::string layer_id = makeTexcoordSourceId(
716                                 effective_id, 
717                                 a, 
718                                 this->export_settings->active_uv_only );
719
720                         source.setId(layer_id);
721                         source.setArrayId(layer_id + ARRAY_ID_SUFFIX);
722                         
723                         source.setAccessorCount(totuv);
724                         source.setAccessorStride(2);
725                         COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
726                         param.push_back("S");
727                         param.push_back("T");
728                         
729                         source.prepareToAppendValues();
730                         
731                         for (int index = 0; index < totpoly; index++) {
732                                 MPoly   *mpoly = mpolys+index;
733                                 MLoopUV *mloop = mloops+mpoly->loopstart;
734                                 for (int j = 0; j < mpoly->totloop; j++) {
735                                         source.appendValues(mloop[j].uv[0],
736                                                                                 mloop[j].uv[1]);
737                                 }
738                         }
739                         
740                         source.finish();
741                 }
742         }
743 }
744
745 bool operator<(const Normal &a, const Normal &b)
746 {
747         /* only needed to sort normal vectors and find() them later in a map.*/
748         return a.x < b.x || (a.x == b.x && (a.y < b.y || (a.y == b.y && a.z < b.z)));
749 }
750
751 //creates <source> for normals
752 void GeometryExporter::createNormalsSource(std::string geom_id, Mesh *me, std::vector<Normal>& nor)
753 {
754 #if 0
755         int totverts = dm->getNumVerts(dm);
756         MVert *verts = dm->getVertArray(dm);
757 #endif
758
759         COLLADASW::FloatSourceF source(mSW);
760         source.setId(getIdBySemantics(geom_id, COLLADASW::InputSemantic::NORMAL));
761         source.setArrayId(getIdBySemantics(geom_id, COLLADASW::InputSemantic::NORMAL) +
762                           ARRAY_ID_SUFFIX);
763         source.setAccessorCount((unsigned long)nor.size());
764         source.setAccessorStride(3);
765         COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
766         param.push_back("X");
767         param.push_back("Y");
768         param.push_back("Z");
769         
770         source.prepareToAppendValues();
771
772         std::vector<Normal>::iterator it;
773         for (it = nor.begin(); it != nor.end(); it++) {
774                 Normal& n = *it;
775                 source.appendValues(n.x, n.y, n.z);
776         }
777
778         source.finish();
779 }
780
781 void GeometryExporter::create_normals(std::vector<Normal> &normals, std::vector<BCPolygonNormalsIndices> &polygons_normals, Mesh *me)
782 {
783         std::map<Normal, unsigned int> shared_normal_indices;
784         int last_normal_index = -1;
785
786         MVert *verts  = me->mvert;
787         MLoop *mloops = me->mloop;
788         float(*lnors)[3] = NULL;
789         bool use_custom_normals = false;
790
791         BKE_mesh_calc_normals_split(me);
792         if (CustomData_has_layer(&me->ldata, CD_NORMAL)) {
793                 lnors = (float(*)[3])CustomData_get_layer(&me->ldata, CD_NORMAL);
794                 use_custom_normals = true;
795         }
796
797         for (int poly_index = 0; poly_index < me->totpoly; poly_index++) {
798                 MPoly *mpoly  = &me->mpoly[poly_index];
799                 bool use_vertex_normals = use_custom_normals || mpoly->flag & ME_SMOOTH;
800
801                 if (!use_vertex_normals) {
802                         // For flat faces use face normal as vertex normal:
803
804                         float vector[3];
805                         BKE_mesh_calc_poly_normal(mpoly, mloops+mpoly->loopstart, verts, vector);
806
807                         Normal n = { vector[0], vector[1], vector[2] };
808                         normals.push_back(n);
809                         last_normal_index++;
810                 }
811
812                 BCPolygonNormalsIndices poly_indices;
813                 for (int loop_index = 0; loop_index < mpoly->totloop; loop_index++) {
814                         unsigned int loop_idx = mpoly->loopstart + loop_index;
815                         if (use_vertex_normals) {
816                                 float normalized[3];
817
818                                 if (use_custom_normals) {
819                                         normalize_v3_v3(normalized, lnors[loop_idx]);
820                                 }
821                                 else {
822                                         normal_short_to_float_v3(normalized, verts[mloops[loop_index].v].no);
823                                         normalize_v3(normalized);
824                                 }
825                                 Normal n = { normalized[0], normalized[1], normalized[2] };
826
827                                 if (shared_normal_indices.find(n) != shared_normal_indices.end()) {
828                                         poly_indices.add_index(shared_normal_indices[n]);
829                                 }
830                                 else {
831                                         last_normal_index++;
832                                         poly_indices.add_index(last_normal_index);
833                                         shared_normal_indices[n] = last_normal_index;
834                                         normals.push_back(n);
835                                 }
836                         }
837                         else {
838                                 poly_indices.add_index(last_normal_index);
839                         }
840                 }
841
842                 polygons_normals.push_back(poly_indices);
843         }
844 }
845
846 std::string GeometryExporter::getIdBySemantics(std::string geom_id, COLLADASW::InputSemantic::Semantics type, std::string other_suffix)
847 {
848         return geom_id + getSuffixBySemantic(type) + other_suffix;
849 }
850
851
852 COLLADASW::URI GeometryExporter::getUrlBySemantics(std::string geom_id, COLLADASW::InputSemantic::Semantics type, std::string other_suffix)
853 {
854         
855         std::string id(getIdBySemantics(geom_id, type, other_suffix));
856         return COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, id);
857         
858 }
859
860 COLLADASW::URI GeometryExporter::makeUrl(std::string id)
861 {
862         return COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, id);
863 }
864
865