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