Cleanup: style, whitespace, doxy filepaths
[blender-staging.git] / source / blender / collada / MeshImporter.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, Nathan Letwory.
19  *
20  * ***** END GPL LICENSE BLOCK *****
21  */
22
23 /** \file blender/collada/MeshImporter.cpp
24  *  \ingroup collada
25  */
26
27
28 #include <algorithm>
29
30 #if !defined(WIN32) || defined(FREE_WINDOWS)
31 #include <iostream>
32 #endif
33
34 /* COLLADABU_ASSERT, may be able to remove later */
35 #include "COLLADABUPlatform.h"
36
37 #include "COLLADAFWMeshPrimitive.h"
38 #include "COLLADAFWMeshVertexData.h"
39 #include "COLLADAFWPolygons.h"
40
41 extern "C" {
42         #include "BKE_customdata.h"
43         #include "BKE_displist.h"
44         #include "BKE_global.h"
45         #include "BKE_library.h"
46         #include "BKE_main.h"
47         #include "BKE_material.h"
48         #include "BKE_mesh.h"
49         #include "BKE_object.h"
50
51         #include "BLI_listbase.h"
52         #include "BLI_math.h"
53         #include "BLI_string.h"
54         #include "BLI_edgehash.h"
55
56         #include "MEM_guardedalloc.h"
57 }
58
59 #include "ArmatureImporter.h"
60 #include "MeshImporter.h"
61 #include "collada_utils.h"
62
63 // get node name, or fall back to original id if not present (name is optional)
64 template<class T>
65 static const std::string bc_get_dae_name(T *node)
66 {
67         return node->getName().size() ? node->getName(): node->getOriginalId();
68 }
69
70 static const char *bc_primTypeToStr(COLLADAFW::MeshPrimitive::PrimitiveType type)
71 {
72         switch (type) {
73                 case COLLADAFW::MeshPrimitive::LINES:
74                         return "LINES";
75                 case COLLADAFW::MeshPrimitive::LINE_STRIPS:
76                         return "LINESTRIPS";
77                 case COLLADAFW::MeshPrimitive::POLYGONS:
78                         return "POLYGONS";
79                 case COLLADAFW::MeshPrimitive::POLYLIST:
80                         return "POLYLIST";
81                 case COLLADAFW::MeshPrimitive::TRIANGLES:
82                         return "TRIANGLES";
83                 case COLLADAFW::MeshPrimitive::TRIANGLE_FANS:
84                         return "TRIANGLE_FANS";
85                 case COLLADAFW::MeshPrimitive::TRIANGLE_STRIPS:
86                         return "TRIANGLE_STRIPS";
87                 case COLLADAFW::MeshPrimitive::POINTS:
88                         return "POINTS";
89                 case COLLADAFW::MeshPrimitive::UNDEFINED_PRIMITIVE_TYPE:
90                         return "UNDEFINED_PRIMITIVE_TYPE";
91         }
92         return "UNKNOWN";
93 }
94
95 static const char *bc_geomTypeToStr(COLLADAFW::Geometry::GeometryType type)
96 {
97         switch (type) {
98                 case COLLADAFW::Geometry::GEO_TYPE_MESH:
99                         return "MESH";
100                 case COLLADAFW::Geometry::GEO_TYPE_SPLINE:
101                         return "SPLINE";
102                 case COLLADAFW::Geometry::GEO_TYPE_CONVEX_MESH:
103                         return "CONVEX_MESH";
104                 case COLLADAFW::Geometry::GEO_TYPE_UNKNOWN:
105                 default:
106                         return "UNKNOWN";
107         }
108 }
109
110
111 UVDataWrapper::UVDataWrapper(COLLADAFW::MeshVertexData& vdata) : mVData(&vdata)
112 {
113 }
114
115 #ifdef COLLADA_DEBUG
116 void WVDataWrapper::print()
117 {
118         fprintf(stderr, "UVs:\n");
119         switch (mVData->getType()) {
120                 case COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT:
121                 {
122                         COLLADAFW::ArrayPrimitiveType<float> *values = mVData->getFloatValues();
123                         if (values->getCount()) {
124                                 for (int i = 0; i < values->getCount(); i += 2) {
125                                         fprintf(stderr, "%.1f, %.1f\n", (*values)[i], (*values)[i + 1]);
126                                 }
127                         }
128                 }
129                 break;
130                 case COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE:
131                 {
132                         COLLADAFW::ArrayPrimitiveType<double> *values = mVData->getDoubleValues();
133                         if (values->getCount()) {
134                                 for (int i = 0; i < values->getCount(); i += 2) {
135                                         fprintf(stderr, "%.1f, %.1f\n", (float)(*values)[i], (float)(*values)[i + 1]);
136                                 }
137                         }
138                 }
139                 break;
140         }
141         fprintf(stderr, "\n");
142 }
143 #endif
144
145 void UVDataWrapper::getUV(int uv_index, float *uv)
146 {
147         int stride = mVData->getStride(0);
148         if (stride == 0) stride = 2;
149
150         switch (mVData->getType()) {
151                 case COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT:
152                 {
153                         COLLADAFW::ArrayPrimitiveType<float> *values = mVData->getFloatValues();
154                         if (values->empty()) return;
155                         uv[0] = (*values)[uv_index * stride];
156                         uv[1] = (*values)[uv_index * stride + 1];
157                         
158                 }
159                 break;
160                 case COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE:
161                 {
162                         COLLADAFW::ArrayPrimitiveType<double> *values = mVData->getDoubleValues();
163                         if (values->empty()) return;
164                         uv[0] = (float)(*values)[uv_index * stride];
165                         uv[1] = (float)(*values)[uv_index * stride + 1];
166                         
167                 }
168                 break;
169                 case COLLADAFW::MeshVertexData::DATA_TYPE_UNKNOWN:
170                 default:
171                         fprintf(stderr, "MeshImporter.getUV(): unknown data type\n");
172         }
173 }
174
175 VCOLDataWrapper::VCOLDataWrapper(COLLADAFW::MeshVertexData& vdata) : mVData(&vdata) {}
176
177 void VCOLDataWrapper::get_vcol(int v_index, MLoopCol *mloopcol)
178 {
179         int stride = mVData->getStride(0);
180         if (stride == 0) stride = 3;
181
182         switch (mVData->getType()) {
183                 case COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT:
184                 {
185                         COLLADAFW::ArrayPrimitiveType<float> *values = mVData->getFloatValues();
186                         if (values->empty() || values->getCount() <= (v_index * stride + 2)) return;  // xxx need to create an eror instead
187
188                         mloopcol->r = FTOCHAR((*values)[v_index * stride]);
189                         mloopcol->g = FTOCHAR((*values)[v_index * stride + 1]);
190                         mloopcol->b = FTOCHAR((*values)[v_index * stride + 2]);
191                 }
192                 break;
193
194                 case COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE:
195                 {
196                         COLLADAFW::ArrayPrimitiveType<double> *values = mVData->getDoubleValues();
197                         if (values->empty() || values->getCount() <= (v_index * stride + 2)) return; // xxx need to create an eror instead
198
199                         mloopcol->r = FTOCHAR((*values)[v_index * stride]);
200                         mloopcol->g = FTOCHAR((*values)[v_index * stride + 1]);
201                         mloopcol->b = FTOCHAR((*values)[v_index * stride + 2]);
202                 }
203                 break;
204                 default:
205                         fprintf(stderr, "VCOLDataWrapper.getvcol(): unknown data type\n");
206         }
207
208 }
209
210 MeshImporter::MeshImporter(UnitConverter *unitconv, ArmatureImporter *arm, Scene *sce) : unitconverter(unitconv), scene(sce), armature_importer(arm) {
211 }
212
213 bool MeshImporter::set_poly_indices(MPoly *mpoly, MLoop *mloop, int loop_index, unsigned int *indices, int loop_count)
214 {
215         mpoly->loopstart = loop_index;
216         mpoly->totloop   = loop_count;
217         bool broken_loop = false;
218         for (int index=0; index < loop_count; index++) {
219
220                 /* Test if loop defines a hole */
221                 if (!broken_loop) {
222                         for (int i = 0; i < index; i++) {
223                                 if (indices[i] == indices[index]) {
224                                         // duplicate index -> not good
225                                         broken_loop = true;
226                                 }
227                         }
228                 }
229
230                 mloop->v = indices[index];
231                 mloop++;
232         }
233         return broken_loop;
234 }
235
236 void MeshImporter::set_vcol(MLoopCol *mlc, VCOLDataWrapper &vob, int loop_index, COLLADAFW::IndexList &index_list, int count)
237 {
238         int index;
239         for (index = 0; index < count; index++, mlc++) {
240                 int v_index = index_list.getIndex(index + loop_index);
241                 vob.get_vcol(v_index,mlc);
242         }
243 }
244
245 void MeshImporter::set_face_uv(MLoopUV *mloopuv, UVDataWrapper &uvs,
246                                int start_index, COLLADAFW::IndexList& index_list, int count)
247 {
248         // per face vertex indices, this means for quad we have 4 indices, not 8
249         COLLADAFW::UIntValuesArray& indices = index_list.getIndices();
250
251         for (int index = 0; index < count; index++) {
252                 int uv_index = indices[index+start_index];
253                 uvs.getUV(uv_index, mloopuv[index].uv);
254         }
255 }
256
257 #ifdef COLLADA_DEBUG
258 void MeshImporter::print_index_list(COLLADAFW::IndexList& index_list)
259 {
260         fprintf(stderr, "Index list for \"%s\":\n", index_list.getName().c_str());
261         for (int i = 0; i < index_list.getIndicesCount(); i += 2) {
262                 fprintf(stderr, "%u, %u\n", index_list.getIndex(i), index_list.getIndex(i + 1));
263         }
264         fprintf(stderr, "\n");
265 }
266 #endif
267
268 bool MeshImporter::is_nice_mesh(COLLADAFW::Mesh *mesh)  // checks if mesh has supported primitive types: lines, polylist, triangles, triangle_fans
269 {
270         COLLADAFW::MeshPrimitiveArray& prim_arr = mesh->getMeshPrimitives();
271
272         const std::string &name = bc_get_dae_name(mesh);
273
274         for (unsigned i = 0; i < prim_arr.getCount(); i++) {
275
276                 COLLADAFW::MeshPrimitive *mp = prim_arr[i];
277                 COLLADAFW::MeshPrimitive::PrimitiveType type = mp->getPrimitiveType();
278
279                 const char *type_str = bc_primTypeToStr(type);
280
281                 // OpenCollada passes POLYGONS type for <polylist>
282                 if (type == COLLADAFW::MeshPrimitive::POLYLIST || type == COLLADAFW::MeshPrimitive::POLYGONS) {
283
284                         COLLADAFW::Polygons *mpvc = (COLLADAFW::Polygons *)mp;
285                         COLLADAFW::Polygons::VertexCountArray& vca = mpvc->getGroupedVerticesVertexCountArray();
286
287                         int hole_count = 0;
288                         int nonface_count = 0;
289
290                         for (unsigned int j = 0; j < vca.getCount(); j++) {
291                                 int count = vca[j];
292                                 if (abs(count) < 3) {
293                                         nonface_count++;
294                                 }
295
296                                 if (count < 0) {
297                                         hole_count ++;
298                                 }
299                         }
300
301                         if (hole_count > 0) {
302                                 fprintf(stderr, "WARNING: Primitive %s in %s: %d holes not imported (unsupported)\n", type_str, name.c_str(), hole_count);
303                         }
304
305                         if (nonface_count > 0) {
306                                 fprintf(stderr, "WARNING: Primitive %s in %s: %d faces with vertex count < 3 (rejected)\n", type_str, name.c_str(), nonface_count);
307                         }
308                 }
309
310                 else if (type == COLLADAFW::MeshPrimitive::LINES) {
311                         // TODO: Add Checker for line syntax here
312                 }
313
314                 else if (type != COLLADAFW::MeshPrimitive::TRIANGLES && type != COLLADAFW::MeshPrimitive::TRIANGLE_FANS) {
315                         fprintf(stderr, "ERROR: Primitive type %s is not supported.\n", type_str);
316                         return false;
317                 }
318         }
319         
320         if (mesh->getPositions().empty()) {
321                 fprintf(stderr, "ERROR: Mesh %s has no vertices.\n", name.c_str());
322                 return false;
323         }
324
325         return true;
326 }
327
328 void MeshImporter::read_vertices(COLLADAFW::Mesh *mesh, Mesh *me)
329 {
330         // vertices
331         COLLADAFW::MeshVertexData& pos = mesh->getPositions();
332         int stride = pos.getStride(0);
333         if (stride == 0) stride = 3;
334         
335         me->totvert = mesh->getPositions().getFloatValues()->getCount() / stride;
336         me->mvert = (MVert *)CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, me->totvert);
337
338         MVert *mvert;
339         int i;
340
341         for (i = 0, mvert = me->mvert; i < me->totvert; i++, mvert++) {
342                 get_vector(mvert->co, pos, i, stride);
343         }
344 }
345
346
347 // =====================================================================
348 // condition 1: The Primitive has normals
349 // condition 2: The number of normals equals the number of faces.
350 // return true if both conditions apply.
351 // return false otherwise.
352 // =====================================================================
353 bool MeshImporter::primitive_has_useable_normals(COLLADAFW::MeshPrimitive *mp) {
354
355         bool has_useable_normals = false;
356
357         int normals_count = mp->getNormalIndices().getCount();
358         if (normals_count > 0) {
359                 int index_count   = mp->getPositionIndices().getCount();
360                 if (index_count == normals_count) 
361                         has_useable_normals = true;
362                 else {
363                         fprintf(stderr,
364                                 "Warning: Number of normals %d is different from the number of vertices %d, skipping normals\n",
365                                 normals_count, index_count);
366                 }
367         }
368
369         return has_useable_normals;
370
371 }
372
373 // =====================================================================
374 // Assume that only TRIANGLES, TRIANGLE_FANS, POLYLIST and POLYGONS
375 // have faces. (to be verified)
376 // =====================================================================
377 bool MeshImporter::primitive_has_faces(COLLADAFW::MeshPrimitive *mp) {
378
379         bool has_faces = false;
380         int type = mp->getPrimitiveType();
381         switch (type) {
382                 case COLLADAFW::MeshPrimitive::TRIANGLES:
383                 case COLLADAFW::MeshPrimitive::TRIANGLE_FANS:
384                 case COLLADAFW::MeshPrimitive::POLYLIST:
385                 case COLLADAFW::MeshPrimitive::POLYGONS:
386                 {
387                         has_faces = true;
388                         break;
389                 }
390                 default: {
391                         has_faces = false; 
392                         break;
393                 }
394         }
395         return has_faces;
396 }
397
398
399 static std::string extract_vcolname(const COLLADAFW::String &collada_id) {
400         std::string colname =  collada_id;
401         int spos = colname.find("-mesh-colors-");
402         if (spos != std::string::npos) {
403                 colname = colname.substr(spos+13);
404         }
405         return colname;
406 }
407
408
409 // =================================================================
410 // Return the number of faces by summing up
411 // the facecounts of the parts.
412 // hint: This is done because mesh->getFacesCount() does
413 // count loose edges as extra faces, which is not what we want here.
414 // =================================================================
415 void MeshImporter::allocate_poly_data(COLLADAFW::Mesh *collada_mesh, Mesh *me)
416 {
417         COLLADAFW::MeshPrimitiveArray& prim_arr = collada_mesh->getMeshPrimitives();
418         int total_poly_count  = 0;
419         int total_loop_count  = 0;
420
421         // collect edge_count and face_count from all parts
422         for (int i = 0; i < prim_arr.getCount(); i++) {
423                 COLLADAFW::MeshPrimitive *mp = prim_arr[i];
424                 int type = mp->getPrimitiveType();
425                 switch (type) {
426                         case COLLADAFW::MeshPrimitive::TRIANGLES:
427                         case COLLADAFW::MeshPrimitive::TRIANGLE_FANS:
428                         case COLLADAFW::MeshPrimitive::POLYLIST:
429                         case COLLADAFW::MeshPrimitive::POLYGONS:
430                         {
431                                 COLLADAFW::Polygons *mpvc = (COLLADAFW::Polygons *)mp;
432                                 size_t prim_poly_count    = mpvc->getFaceCount();
433
434                                 size_t prim_loop_count    = 0;
435                                 for (int index=0; index < prim_poly_count; index++) 
436                                 {
437                                         int vcount = get_vertex_count(mpvc, index);
438                                         if (vcount > 0) {
439                                                 prim_loop_count += vcount;
440                                                 total_poly_count++;
441                                         }
442                                         else {
443                                                 // TODO: this is a hole and not another polygon!
444                                         }
445                                 }
446
447                                 total_loop_count += prim_loop_count;
448
449                                 break;
450                         }
451                         default:
452                                 break;
453                 }
454         }
455
456         // Add the data containers
457         if (total_poly_count > 0) {
458                 me->totpoly = total_poly_count;
459                 me->totloop = total_loop_count;
460                 me->mpoly   = (MPoly *)CustomData_add_layer(&me->pdata, CD_MPOLY, CD_CALLOC, NULL, me->totpoly);
461                 me->mloop   = (MLoop *)CustomData_add_layer(&me->ldata, CD_MLOOP, CD_CALLOC, NULL, me->totloop);
462
463                 unsigned int totuvset = collada_mesh->getUVCoords().getInputInfosArray().getCount();
464                 for (int i = 0; i < totuvset; i++) {
465                         if (collada_mesh->getUVCoords().getLength(i) == 0) {
466                                 totuvset = 0;
467                                 break;
468                         }
469                 }
470
471                 if (totuvset > 0) {
472                         for (int i = 0; i < totuvset; i++) {
473                                 COLLADAFW::MeshVertexData::InputInfos *info = collada_mesh->getUVCoords().getInputInfosArray()[i];
474                                 COLLADAFW::String &uvname = info->mName;
475                                 // Allocate space for UV_data
476                                 CustomData_add_layer_named(&me->pdata, CD_MTEXPOLY, CD_DEFAULT, NULL, me->totpoly, uvname.c_str());
477                                 CustomData_add_layer_named(&me->ldata, CD_MLOOPUV, CD_DEFAULT, NULL, me->totloop, uvname.c_str());
478                         }
479                         // activate the first uv map
480                         me->mtpoly  = (MTexPoly *)CustomData_get_layer_n(&me->pdata, CD_MTEXPOLY, 0);
481                         me->mloopuv = (MLoopUV *) CustomData_get_layer_n(&me->ldata, CD_MLOOPUV, 0);
482                 }
483
484                 int totcolset = collada_mesh->getColors().getInputInfosArray().getCount();
485                 if (totcolset > 0) {
486                         for (int i = 0; i < totcolset; i++) {
487                                 COLLADAFW::MeshVertexData::InputInfos *info = collada_mesh->getColors().getInputInfosArray()[i];
488                                 COLLADAFW::String colname = extract_vcolname(info->mName);
489                                 CustomData_add_layer_named(&me->ldata,CD_MLOOPCOL,CD_DEFAULT,NULL,me->totloop, colname.c_str());
490                         }
491                         me->mloopcol = (MLoopCol *) CustomData_get_layer_n(&me->ldata, CD_MLOOPCOL, 0);
492                 }
493
494         }
495 }
496
497 unsigned int MeshImporter::get_vertex_count(COLLADAFW::Polygons *mp, int index) {
498         int type = mp->getPrimitiveType();
499         int result;
500         switch (type) {
501                 case COLLADAFW::MeshPrimitive::TRIANGLES:
502                 case COLLADAFW::MeshPrimitive::TRIANGLE_FANS:
503                 {
504                         result = 3;
505                         break;
506                 }
507                 case COLLADAFW::MeshPrimitive::POLYLIST:
508                 case COLLADAFW::MeshPrimitive::POLYGONS:
509                 {
510                         result = mp->getGroupedVerticesVertexCountArray()[index];
511                         break;
512                 }
513                 default:
514                 {
515                         result = -1;
516                         break;
517                 }
518         }
519         return result;
520 }
521
522
523 unsigned int MeshImporter::get_loose_edge_count(COLLADAFW::Mesh *mesh) {
524         COLLADAFW::MeshPrimitiveArray& prim_arr = mesh->getMeshPrimitives();
525         int loose_edge_count = 0;
526
527         // collect edge_count and face_count from all parts
528         for (int i = 0; i < prim_arr.getCount(); i++) {
529                 COLLADAFW::MeshPrimitive *mp = prim_arr[i];
530                 int type = mp->getPrimitiveType();
531                 switch (type) {
532                         case COLLADAFW::MeshPrimitive::LINES:
533                         {
534                                 size_t prim_totface = mp->getFaceCount();
535                                 loose_edge_count += prim_totface;
536                                 break;
537                         }
538                         default:
539                                 break;
540                 }
541         }
542         return loose_edge_count;
543 }
544
545 // =================================================================
546 // This functin is copied from source/blender/editors/mesh/mesh_data.c
547 //
548 // TODO: (As discussed with sergey-) :
549 // Maybe move this function to blenderkernel/intern/mesh.c 
550 // and add definition to BKE_mesh.c
551 // =================================================================
552 void MeshImporter::mesh_add_edges(Mesh *mesh, int len)
553 {
554         CustomData edata;
555         MEdge *medge;
556         int i, totedge;
557
558         if (len == 0)
559                 return;
560
561         totedge = mesh->totedge + len;
562
563         /* update customdata  */
564         CustomData_copy(&mesh->edata, &edata, CD_MASK_MESH, CD_DEFAULT, totedge);
565         CustomData_copy_data(&mesh->edata, &edata, 0, 0, mesh->totedge);
566
567         if (!CustomData_has_layer(&edata, CD_MEDGE))
568                 CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, NULL, totedge);
569
570         CustomData_free(&mesh->edata, mesh->totedge);
571         mesh->edata = edata;
572         BKE_mesh_update_customdata_pointers(mesh, false); /* new edges don't change tessellation */
573
574         /* set default flags */
575         medge = &mesh->medge[mesh->totedge];
576         for (i = 0; i < len; i++, medge++)
577                 medge->flag = ME_EDGEDRAW | ME_EDGERENDER | SELECT;
578
579         mesh->totedge = totedge;
580 }
581
582 // =================================================================
583 // Read all loose edges.
584 // Important: This function assumes that all edges from existing 
585 // faces have allready been generated and added to me->medge
586 // So this function MUST be called after read_faces() (see below)
587 // =================================================================
588 void MeshImporter::read_lines(COLLADAFW::Mesh *mesh, Mesh *me)
589 {
590         unsigned int loose_edge_count = get_loose_edge_count(mesh);
591         if (loose_edge_count > 0) {
592
593                 unsigned int face_edge_count  = me->totedge;
594                 /* unsigned int total_edge_count = loose_edge_count + face_edge_count; */ /* UNUSED */
595                 
596                 mesh_add_edges(me, loose_edge_count);
597                 MEdge *med = me->medge + face_edge_count;
598
599                 COLLADAFW::MeshPrimitiveArray& prim_arr = mesh->getMeshPrimitives();
600
601                 for (int i = 0; i < prim_arr.getCount(); i++) {
602                         
603                         COLLADAFW::MeshPrimitive *mp = prim_arr[i];
604
605                         int type = mp->getPrimitiveType();
606                         if (type == COLLADAFW::MeshPrimitive::LINES) {
607                                 unsigned int edge_count  = mp->getFaceCount();
608                                 unsigned int *indices    = mp->getPositionIndices().getData();
609                                 
610                                 for (int i = 0; i < edge_count; i++, med++) {
611                                         med->bweight = 0;
612                                         med->crease  = 0;
613                                         med->flag   |= ME_LOOSEEDGE;
614                                         med->v1      = indices[2 * i];
615                                         med->v2      = indices[2 * i + 1];
616                                 }
617                         }
618                 }
619
620         }
621 }
622
623
624 // =======================================================================
625 // Read all faces from TRIANGLES, TRIANGLE_FANS, POLYLIST, POLYGON
626 // Important: This function MUST be called before read_lines() 
627 // Otherwise we will loose all edges from faces (see read_lines() above)
628 //
629 // TODO: import uv set names
630 // ========================================================================
631 void MeshImporter::read_polys(COLLADAFW::Mesh *collada_mesh, Mesh *me)
632 {
633         unsigned int i;
634         
635         allocate_poly_data(collada_mesh, me);
636
637         UVDataWrapper uvs(collada_mesh->getUVCoords());
638         VCOLDataWrapper vcol(collada_mesh->getColors());
639
640         MPoly *mpoly = me->mpoly;
641         MLoop *mloop = me->mloop;
642         int loop_index = 0;
643
644         MaterialIdPrimitiveArrayMap mat_prim_map;
645
646         COLLADAFW::MeshPrimitiveArray& prim_arr = collada_mesh->getMeshPrimitives();
647         COLLADAFW::MeshVertexData& nor = collada_mesh->getNormals();
648
649         for (i = 0; i < prim_arr.getCount(); i++) {
650                 
651                 COLLADAFW::MeshPrimitive *mp = prim_arr[i];
652
653                 // faces
654                 size_t prim_totpoly                           = mp->getFaceCount();
655                 unsigned int *position_indices                = mp->getPositionIndices().getData();
656                 unsigned int *normal_indices                  = mp->getNormalIndices().getData();
657
658
659                 bool mp_has_normals = primitive_has_useable_normals(mp);
660                 bool mp_has_faces   = primitive_has_faces(mp);
661
662                 int collada_meshtype = mp->getPrimitiveType();
663                 
664                 // since we cannot set mpoly->mat_nr here, we store a portion of me->mpoly in Primitive
665                 Primitive prim = {mpoly, 0};
666
667                 // If MeshPrimitive is TRIANGLE_FANS we split it into triangles
668                 // The first trifan vertex will be the first vertex in every triangle
669                 // XXX The proper function of TRIANGLE_FANS is not tested!!!
670                 // XXX In particular the handling of the normal_indices looks very wrong to me
671                 if (collada_meshtype == COLLADAFW::MeshPrimitive::TRIANGLE_FANS) {
672                         unsigned grouped_vertex_count = mp->getGroupedVertexElementsCount();
673                         for (unsigned int group_index = 0; group_index < grouped_vertex_count; group_index++) {
674                                 unsigned int first_vertex = position_indices[0]; // Store first trifan vertex
675                                 unsigned int first_normal = normal_indices[0]; // Store first trifan vertex normal
676                                 unsigned int vertex_count = mp->getGroupedVerticesVertexCount(group_index);
677
678                                 for (unsigned int vertex_index = 0; vertex_index < vertex_count - 2; vertex_index++) {
679                                         // For each triangle store indeces of its 3 vertices
680                                         unsigned int triangle_vertex_indices[3] = {first_vertex, position_indices[1], position_indices[2]};
681                                         set_poly_indices(mpoly, mloop, loop_index, triangle_vertex_indices, 3);
682
683                                         if (mp_has_normals) {  // vertex normals, same inplementation as for the triangles
684                                                 // the same for vertces normals
685                                                 unsigned int vertex_normal_indices[3] = {first_normal, normal_indices[1], normal_indices[2]};
686                                                 if (!is_flat_face(vertex_normal_indices, nor, 3))
687                                                         mpoly->flag |= ME_SMOOTH;
688                                                 normal_indices++;
689                                         }
690                                 
691                                         mpoly++;
692                                         mloop += 3;
693                                         loop_index += 3;
694                                         prim.totpoly++;
695
696                                 }
697
698                                 // Moving cursor  to the next triangle fan.
699                                 if (mp_has_normals)
700                                         normal_indices += 2;
701
702                                 position_indices +=  2;
703                         }
704                 }
705
706                 if (collada_meshtype == COLLADAFW::MeshPrimitive::POLYLIST ||
707                         collada_meshtype == COLLADAFW::MeshPrimitive::POLYGONS ||
708                         collada_meshtype == COLLADAFW::MeshPrimitive::TRIANGLES) {
709                         COLLADAFW::Polygons *mpvc = (COLLADAFW::Polygons *)mp;
710                         unsigned int start_index = 0;
711
712                         COLLADAFW::IndexListArray& index_list_array_uvcoord = mp->getUVCoordIndicesArray();
713                         COLLADAFW::IndexListArray& index_list_array_vcolor  = mp->getColorIndicesArray();
714
715                         int invalid_loop_holes = 0;
716                         for (unsigned int j = 0; j < prim_totpoly; j++) {
717
718                                 // Vertices in polygon:
719                                 int vcount = get_vertex_count(mpvc, j);
720                                 if (vcount < 0) {
721                                         continue; // TODO: add support for holes
722                                 }
723
724                                 bool broken_loop = set_poly_indices(mpoly, mloop, loop_index, position_indices, vcount);
725                                 if (broken_loop)
726                                 {
727                                         invalid_loop_holes += 1;
728                                 }
729
730                                 for (unsigned int uvset_index = 0; uvset_index < index_list_array_uvcoord.getCount(); uvset_index++) {
731                                         // get mtface by face index and uv set index
732                                         COLLADAFW::IndexList& index_list = *index_list_array_uvcoord[uvset_index];
733                                         MLoopUV  *mloopuv = (MLoopUV  *)CustomData_get_layer_named(&me->ldata, CD_MLOOPUV, index_list.getName().c_str());
734                                         if (mloopuv == NULL) {
735                                                 fprintf(stderr, "Collada import: Mesh [%s] : Unknown reference to TEXCOORD [#%s].\n", me->id.name, index_list.getName().c_str() );
736                                         }
737                                         else {
738                                                 set_face_uv(mloopuv+loop_index, uvs, start_index, *index_list_array_uvcoord[uvset_index], vcount);
739                                         }
740                                 }
741
742                                 if (mp_has_normals) {
743                                         if (!is_flat_face(normal_indices, nor, vcount))
744                                                 mpoly->flag |= ME_SMOOTH;
745                                 }
746
747
748                                 if (mp->hasColorIndices()) {
749                                         int vcolor_count = index_list_array_vcolor.getCount();
750
751                                         for (unsigned int vcolor_index = 0; vcolor_index < vcolor_count; vcolor_index++) {
752
753                                                 COLLADAFW::IndexList& color_index_list = *mp->getColorIndices(vcolor_index);
754                                                 COLLADAFW::String colname = extract_vcolname(color_index_list.getName());
755                                                 MLoopCol *mloopcol = (MLoopCol  *)CustomData_get_layer_named(&me->ldata, CD_MLOOPCOL, colname.c_str());
756                                                 if (mloopcol == NULL) {
757                                                         fprintf(stderr, "Collada import: Mesh [%s] : Unknown reference to VCOLOR [#%s].\n", me->id.name, color_index_list.getName().c_str());
758                                                 }
759                                                 else {
760                                                         set_vcol(mloopcol + loop_index, vcol, start_index, color_index_list, vcount);
761                                                 }
762                                         }
763                                 }
764
765                                 mpoly++;
766                                 mloop       += vcount;
767                                 loop_index  += vcount;
768                                 start_index += vcount;
769                                 prim.totpoly++;
770
771                                 if (mp_has_normals)
772                                         normal_indices += vcount;
773
774                                 position_indices += vcount;
775                         }
776
777                         if (invalid_loop_holes > 0)
778                         {
779                                 fprintf(stderr, "Collada import: Mesh [%s] : contains %d unsupported loops (holes).\n", me->id.name, invalid_loop_holes);
780                         }
781                 }
782
783                 else if (collada_meshtype == COLLADAFW::MeshPrimitive::LINES) {
784                         continue; // read the lines later after all the rest is done
785                 }
786
787                 if (mp_has_faces)
788                         mat_prim_map[mp->getMaterialId()].push_back(prim);
789
790
791         }
792
793         geom_uid_mat_mapping_map[collada_mesh->getUniqueId()] = mat_prim_map;
794 }
795
796 void MeshImporter::get_vector(float v[3], COLLADAFW::MeshVertexData& arr, int i, int stride)
797 {
798         i *= stride;
799         
800         switch (arr.getType()) {
801                 case COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT:
802                 {
803                         COLLADAFW::ArrayPrimitiveType<float> *values = arr.getFloatValues();
804                         if (values->empty()) return;
805
806                         v[0] = (*values)[i++];
807                         v[1] = (*values)[i++];
808                         if (stride>=3) {
809                                 v[2] = (*values)[i];
810                         }
811                         else {
812                                 v[2] = 0.0f;
813                         }
814
815                 }
816                 break;
817                 case COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE:
818                 {
819                         COLLADAFW::ArrayPrimitiveType<double> *values = arr.getDoubleValues();
820                         if (values->empty()) return;
821
822                         v[0] = (float)(*values)[i++];
823                         v[1] = (float)(*values)[i++];
824                         if (stride >= 3) {
825                                 v[2] = (float)(*values)[i];
826                         }
827                         else {
828                                 v[2] = 0.0f;
829                         }
830                 }
831                 break;
832                 default:
833                         break;
834         }
835 }
836
837 bool MeshImporter::is_flat_face(unsigned int *nind, COLLADAFW::MeshVertexData& nor, int count)
838 {
839         float a[3], b[3];
840
841         get_vector(a, nor, *nind, 3);
842         normalize_v3(a);
843
844         nind++;
845
846         for (int i = 1; i < count; i++, nind++) {
847                 get_vector(b, nor, *nind, 3);
848                 normalize_v3(b);
849
850                 float dp = dot_v3v3(a, b);
851
852                 if (dp < 0.99999f || dp > 1.00001f)
853                         return false;
854         }
855
856         return true;
857 }
858
859 Object *MeshImporter::get_object_by_geom_uid(const COLLADAFW::UniqueId& geom_uid)
860 {
861         if (uid_object_map.find(geom_uid) != uid_object_map.end())
862                 return uid_object_map[geom_uid];
863         return NULL;
864 }
865
866 Mesh *MeshImporter::get_mesh_by_geom_uid(const COLLADAFW::UniqueId& mesh_uid)
867 {
868         if (uid_mesh_map.find(mesh_uid) != uid_mesh_map.end())
869                 return uid_mesh_map[mesh_uid];
870         return NULL;
871 }
872
873 std::string *MeshImporter::get_geometry_name(const std::string &mesh_name)
874 {
875         if (this->mesh_geom_map.find(mesh_name) != this->mesh_geom_map.end())
876                 return &this->mesh_geom_map[mesh_name];
877         return NULL;
878 }
879
880 MTex *MeshImporter::assign_textures_to_uvlayer(COLLADAFW::TextureCoordinateBinding &ctexture,
881                                                Mesh *me, TexIndexTextureArrayMap& texindex_texarray_map,
882                                                MTex *color_texture)
883 {
884         const COLLADAFW::TextureMapId texture_index = ctexture.getTextureMapId();
885         size_t setindex = ctexture.getSetIndex();
886         std::string uvname = ctexture.getSemantic();
887         
888         if (setindex == -1) return NULL;
889         
890         const CustomData *data = &me->fdata;
891         int layer_index = CustomData_get_layer_index(data, CD_MTFACE);
892
893         if (layer_index == -1) return NULL;
894
895         CustomDataLayer *cdl = &data->layers[layer_index + setindex];
896         
897         /* set uvname to bind_vertex_input semantic */
898         BLI_strncpy(cdl->name, uvname.c_str(), sizeof(cdl->name));
899
900         if (texindex_texarray_map.find(texture_index) == texindex_texarray_map.end()) {
901                 
902                 fprintf(stderr, "Cannot find texture array by texture index.\n");
903                 return color_texture;
904         }
905         
906         std::vector<MTex *> textures = texindex_texarray_map[texture_index];
907         
908         std::vector<MTex *>::iterator it;
909         
910         for (it = textures.begin(); it != textures.end(); it++) {
911                 
912                 MTex *texture = *it;
913                 
914                 if (texture) {
915                         BLI_strncpy(texture->uvname, uvname.c_str(), sizeof(texture->uvname));
916                         if (texture->mapto == MAP_COL) color_texture = texture;
917                 }
918         }
919         return color_texture;
920 }
921
922 /**
923  * this function checks if both objects have the same
924  * materials assigned to Object (in the same order)
925  * returns true if condition matches, otherwise false;
926  **/
927 static bool bc_has_same_material_configuration(Object *ob1, Object *ob2)
928 {
929         if (ob1->totcol != ob2->totcol) return false; // not same number of materials
930         if (ob1->totcol == 0) return false; // no material at all
931         
932         for (int index=0; index < ob1->totcol; index++) {
933                 if (ob1->matbits[index] != ob2->matbits[index]) return false; // shouldn't happen
934                 if (ob1->matbits[index] == 0) return false; // shouldn't happen
935                 if (ob1->mat[index] != ob2->mat[index]) return false; // different material assignment
936         }
937         return true;
938 }
939
940
941 /**
942  *
943  * Caution here: This code assumes tha all materials are assigned to Object
944  * and no material is assigned to Data.
945  * That is true right after the objects have been imported.
946  *
947  **/
948 static void bc_copy_materials_to_data(Object *ob, Mesh *me)
949 {
950         for (int index = 0; index < ob->totcol; index++) {
951                 ob->matbits[index] = 0;
952                 me->mat[index] = ob->mat[index];
953         }
954 }
955
956 /**
957  *
958  * Remove all references to materials from the object
959  *
960  **/
961 static void bc_remove_materials_from_object(Object *ob, Mesh *me)
962 {
963         for (int index = 0; index < ob->totcol; index++) {
964                 ob->matbits[index] = 0;
965                 ob->mat[index] = NULL;
966         }
967 }
968
969 /**
970  * Returns the list of Users of the given Mesh object.
971  * Note: This function uses the object user flag to control
972  * which objects have already been processed.
973  **/
974 std::vector<Object *> MeshImporter::get_all_users_of(Mesh *reference_mesh)
975 {
976         std::vector<Object *> mesh_users;
977         for (std::vector<Object *>::iterator it = imported_objects.begin();
978              it != imported_objects.end(); ++it)
979         {
980                 Object *ob = (*it);
981                 if (bc_is_marked(ob)) {
982                         bc_remove_mark(ob);
983                         Mesh *me = (Mesh *) ob->data;
984                         if (me == reference_mesh)
985                                 mesh_users.push_back(ob);
986                 }
987         }
988         return mesh_users;
989 }
990
991 /**
992  *
993  * During import all materials have been assigned to Object.
994  * Now we iterate over the imported objects and optimize
995  * the assignments as follows:
996  *
997  * for each imported geometry:
998  *     if number of users is 1:
999  *         get the user (object)
1000  *         move the materials from Object to Data
1001  *     else:
1002  *         determine which materials are assigned to the first user
1003  *         check if all other users have the same materials in the same order
1004  *         if the check is positive:
1005  *             Add the materials of the first user to the geometry
1006  *             adjust all other users accordingly.
1007  *
1008  **/
1009 void MeshImporter::optimize_material_assignements()
1010 {
1011         for (std::vector<Object *>::iterator it = imported_objects.begin();
1012              it != imported_objects.end(); ++it)
1013         {
1014                 Object *ob = (*it);
1015                 Mesh *me = (Mesh *) ob->data;
1016                 if (me->id.us==1) {
1017                         bc_copy_materials_to_data(ob, me);
1018                         bc_remove_materials_from_object(ob, me);
1019                         bc_remove_mark(ob);
1020                 }
1021                 else if (me->id.us > 1)
1022                 {
1023                         bool can_move = true;
1024                         std::vector<Object *> mesh_users = get_all_users_of(me);
1025                         if (mesh_users.size() > 1)
1026                         {
1027                                 Object *ref_ob = mesh_users[0];
1028                                 for (int index = 1; index < mesh_users.size(); index++) {
1029                                         if (!bc_has_same_material_configuration(ref_ob, mesh_users[index])) {
1030                                                 can_move = false;
1031                                                 break;
1032                                         }
1033                                 }
1034                                 if (can_move) {
1035                                         bc_copy_materials_to_data(ref_ob, me);
1036                                         for (int index = 0; index < mesh_users.size(); index++) {
1037                                                 Object *object = mesh_users[index];
1038                                                 bc_remove_materials_from_object(object, me);
1039                                                 bc_remove_mark(object);
1040                                         }
1041                                 }
1042                         }
1043                 }
1044         }
1045 }
1046
1047 /**
1048  * We do not know in advance which objects will share geometries.
1049  * And we do not know either if the objects which share geometries
1050  * come along with different materials. So we first create the objects
1051  * and assign the materials to Object, then in a later cleanup we decide
1052  * which materials shall be moved to the created geometries. Also see
1053  * optimize_material_assignements() above.
1054  */
1055 MTFace *MeshImporter::assign_material_to_geom(COLLADAFW::MaterialBinding cmaterial,
1056                                               std::map<COLLADAFW::UniqueId, Material *>& uid_material_map,
1057                                               Object *ob, const COLLADAFW::UniqueId *geom_uid,
1058                                               char *layername, MTFace *texture_face,
1059                                               std::map<Material *, TexIndexTextureArrayMap>& material_texture_mapping_map, short mat_index)
1060 {
1061         MTex *color_texture = NULL;
1062         Mesh *me = (Mesh *)ob->data;
1063         const COLLADAFW::UniqueId& ma_uid = cmaterial.getReferencedMaterial();
1064         
1065         // do we know this material?
1066         if (uid_material_map.find(ma_uid) == uid_material_map.end()) {
1067                 
1068                 fprintf(stderr, "Cannot find material by UID.\n");
1069                 return NULL;
1070         }
1071
1072         // first time we get geom_uid, ma_uid pair. Save for later check.
1073         materials_mapped_to_geom.insert(std::pair<COLLADAFW::UniqueId, COLLADAFW::UniqueId>(*geom_uid, ma_uid));
1074         
1075         Material *ma = uid_material_map[ma_uid];
1076
1077         // Attention! This temporaly assigns material to object on purpose!
1078         // See note above.
1079         ob->actcol=0;
1080         assign_material(ob, ma, mat_index + 1, BKE_MAT_ASSIGN_OBJECT); 
1081         
1082         COLLADAFW::TextureCoordinateBindingArray& tex_array = 
1083             cmaterial.getTextureCoordinateBindingArray();
1084         TexIndexTextureArrayMap texindex_texarray_map = material_texture_mapping_map[ma];
1085         unsigned int i;
1086         // loop through <bind_vertex_inputs>
1087         for (i = 0; i < tex_array.getCount(); i++) {
1088                 
1089                 color_texture = assign_textures_to_uvlayer(tex_array[i], me, texindex_texarray_map,
1090                                                             color_texture);
1091         }
1092         
1093         // set texture face
1094         if (color_texture &&
1095             strlen((color_texture)->uvname) &&
1096             !STREQ(layername, color_texture->uvname)) {
1097                 texture_face = (MTFace *)CustomData_get_layer_named(&me->fdata, CD_MTFACE,
1098                                                                     color_texture->uvname);
1099                 strcpy(layername, color_texture->uvname);
1100         }
1101         
1102         MaterialIdPrimitiveArrayMap& mat_prim_map = geom_uid_mat_mapping_map[*geom_uid];
1103         COLLADAFW::MaterialId mat_id = cmaterial.getMaterialId();
1104         
1105         // assign material indices to mesh faces
1106         if (mat_prim_map.find(mat_id) != mat_prim_map.end()) {
1107                 
1108                 std::vector<Primitive>& prims = mat_prim_map[mat_id];
1109                 
1110                 std::vector<Primitive>::iterator it;
1111                 
1112                 for (it = prims.begin(); it != prims.end(); it++) {
1113                         Primitive& prim = *it;
1114                         MPoly *mpoly = prim.mpoly;
1115
1116                         for (i = 0; i < prim.totpoly; i++, mpoly++) {
1117                                 mpoly->mat_nr = mat_index;
1118                                 // bind texture images to faces
1119                                 if (texture_face && color_texture) {
1120                                         texture_face->tpage = (Image *)color_texture->tex->ima;
1121                                         texture_face++;
1122                                 }
1123                         }
1124                 }
1125         }       
1126         return texture_face;
1127 }
1128
1129 Object *MeshImporter::create_mesh_object(COLLADAFW::Node *node, COLLADAFW::InstanceGeometry *geom,
1130                                          bool isController,
1131                                          std::map<COLLADAFW::UniqueId, Material *>& uid_material_map,
1132                                          std::map<Material *, TexIndexTextureArrayMap>& material_texture_mapping_map)
1133 {
1134         const COLLADAFW::UniqueId *geom_uid = &geom->getInstanciatedObjectId();
1135         
1136         // check if node instanciates controller or geometry
1137         if (isController) {
1138                 
1139                 geom_uid = armature_importer->get_geometry_uid(*geom_uid);
1140                 
1141                 if (!geom_uid) {
1142                         fprintf(stderr, "Couldn't find a mesh UID by controller's UID.\n");
1143                         return NULL;
1144                 }
1145         }
1146         else {
1147                 
1148                 if (uid_mesh_map.find(*geom_uid) == uid_mesh_map.end()) {
1149                         // this could happen if a mesh was not created
1150                         // (e.g. if it contains unsupported geometry)
1151                         fprintf(stderr, "Couldn't find a mesh by UID.\n");
1152                         return NULL;
1153                 }
1154         }
1155         if (!uid_mesh_map[*geom_uid]) return NULL;
1156         
1157         // name Object
1158         const std::string& id = node->getName().size() ? node->getName() : node->getOriginalId();
1159         const char *name = (id.length()) ? id.c_str() : NULL;
1160         
1161         // add object
1162         Object *ob = bc_add_object(scene, OB_MESH, name);
1163         bc_set_mark(ob); // used later for material assignement optimization
1164
1165
1166         // store object pointer for ArmatureImporter
1167         uid_object_map[*geom_uid] = ob;
1168         imported_objects.push_back(ob);
1169         
1170         // replace ob->data freeing the old one
1171         Mesh *old_mesh = (Mesh *)ob->data;
1172         Mesh *new_mesh = uid_mesh_map[*geom_uid];
1173
1174         BKE_mesh_assign_object(ob, new_mesh);
1175         BKE_mesh_calc_normals(new_mesh);
1176
1177         if (old_mesh->id.us == 0) BKE_libblock_free(G.main, old_mesh);
1178         
1179         char layername[100];
1180         layername[0] = '\0';
1181         MTFace *texture_face = NULL;
1182         
1183         COLLADAFW::MaterialBindingArray& mat_array =
1184             geom->getMaterialBindings();
1185         
1186         // loop through geom's materials
1187         for (unsigned int i = 0; i < mat_array.getCount(); i++) {
1188                 
1189                 if (mat_array[i].getReferencedMaterial().isValid()) {
1190                         texture_face = assign_material_to_geom(mat_array[i], uid_material_map, ob, geom_uid,
1191                                                                layername, texture_face,
1192                                                                material_texture_mapping_map, i);
1193                 }
1194                 else {
1195                         fprintf(stderr, "invalid referenced material for %s\n", mat_array[i].getName().c_str());
1196                 }
1197         }
1198
1199         return ob;
1200 }
1201
1202 // create a mesh storing a pointer in a map so it can be retrieved later by geometry UID
1203 bool MeshImporter::write_geometry(const COLLADAFW::Geometry *geom)
1204 {
1205
1206         if (geom->getType() != COLLADAFW::Geometry::GEO_TYPE_MESH) {
1207                 // TODO: report warning
1208                 fprintf(stderr, "Mesh type %s is not supported\n", bc_geomTypeToStr(geom->getType()));
1209                 return true;
1210         }
1211         
1212         COLLADAFW::Mesh *mesh = (COLLADAFW::Mesh *)geom;
1213         
1214         if (!is_nice_mesh(mesh)) {
1215                 fprintf(stderr, "Ignoring mesh %s\n", bc_get_dae_name(mesh).c_str());
1216                 return true;
1217         }
1218         
1219         const std::string& str_geom_id = mesh->getName().size() ? mesh->getName() : mesh->getOriginalId();
1220         Mesh *me = BKE_mesh_add(G.main, (char *)str_geom_id.c_str());
1221         id_us_min(&me->id); // is already 1 here, but will be set later in BKE_mesh_assign_object
1222
1223         // store the Mesh pointer to link it later with an Object
1224         // mesh_geom_map needed to map mesh to its geometry name (for shape key naming)
1225         this->uid_mesh_map[mesh->getUniqueId()] = me;
1226         this->mesh_geom_map[std::string(me->id.name)] = str_geom_id;
1227         
1228         read_vertices(mesh, me);
1229         read_polys(mesh, me);
1230
1231         // must validate before calculating edges
1232         BKE_mesh_calc_normals(me);
1233         BKE_mesh_validate(me, false, false);
1234         // validation does this
1235         // BKE_mesh_calc_edges(me, false, false);
1236
1237         // read_lines() must be called after the face edges have been generated.
1238         // Oterwise the loose edges will be silently deleted again.
1239         read_lines(mesh, me);
1240
1241         return true;
1242 }