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