2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * Contributor(s): Chingiz Dyussenov, Arystanbek Dyussenov, Nathan Letwory, Trevor Glauz.
20 * ***** END GPL LICENSE BLOCK *****
23 /** \file blender/collada/MeshImporter.cpp
34 /* COLLADABU_ASSERT, may be able to remove later */
35 #include "COLLADABUPlatform.h"
37 #include "COLLADAFWMeshPrimitive.h"
38 #include "COLLADAFWMeshVertexData.h"
39 #include "COLLADAFWPolygons.h"
42 #include "BKE_customdata.h"
43 #include "BKE_displist.h"
44 #include "BKE_global.h"
45 #include "BKE_library.h"
46 #include "BKE_material.h"
48 #include "BKE_object.h"
50 #include "BLI_listbase.h"
52 #include "BLI_string.h"
53 #include "BLI_edgehash.h"
55 #include "MEM_guardedalloc.h"
58 #include "ArmatureImporter.h"
59 #include "MeshImporter.h"
60 #include "collada_utils.h"
62 // get node name, or fall back to original id if not present (name is optional)
64 static const std::string bc_get_dae_name(T *node)
66 return node->getName().size() ? node->getName(): node->getOriginalId();
69 static const char *bc_primTypeToStr(COLLADAFW::MeshPrimitive::PrimitiveType type)
72 case COLLADAFW::MeshPrimitive::LINES:
74 case COLLADAFW::MeshPrimitive::LINE_STRIPS:
76 case COLLADAFW::MeshPrimitive::POLYGONS:
78 case COLLADAFW::MeshPrimitive::POLYLIST:
80 case COLLADAFW::MeshPrimitive::TRIANGLES:
82 case COLLADAFW::MeshPrimitive::TRIANGLE_FANS:
83 return "TRIANGLE_FANS";
84 case COLLADAFW::MeshPrimitive::TRIANGLE_STRIPS:
85 return "TRIANGLE_STRIPS";
86 case COLLADAFW::MeshPrimitive::POINTS:
88 case COLLADAFW::MeshPrimitive::UNDEFINED_PRIMITIVE_TYPE:
89 return "UNDEFINED_PRIMITIVE_TYPE";
94 static const char *bc_geomTypeToStr(COLLADAFW::Geometry::GeometryType type)
97 case COLLADAFW::Geometry::GEO_TYPE_MESH:
99 case COLLADAFW::Geometry::GEO_TYPE_SPLINE:
101 case COLLADAFW::Geometry::GEO_TYPE_CONVEX_MESH:
102 return "CONVEX_MESH";
103 case COLLADAFW::Geometry::GEO_TYPE_UNKNOWN:
110 UVDataWrapper::UVDataWrapper(COLLADAFW::MeshVertexData& vdata) : mVData(&vdata)
115 void WVDataWrapper::print()
117 fprintf(stderr, "UVs:\n");
118 switch (mVData->getType()) {
119 case COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT:
121 COLLADAFW::ArrayPrimitiveType<float> *values = mVData->getFloatValues();
122 if (values->getCount()) {
123 for (int i = 0; i < values->getCount(); i += 2) {
124 fprintf(stderr, "%.1f, %.1f\n", (*values)[i], (*values)[i + 1]);
129 case COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE:
131 COLLADAFW::ArrayPrimitiveType<double> *values = mVData->getDoubleValues();
132 if (values->getCount()) {
133 for (int i = 0; i < values->getCount(); i += 2) {
134 fprintf(stderr, "%.1f, %.1f\n", (float)(*values)[i], (float)(*values)[i + 1]);
140 fprintf(stderr, "\n");
144 void UVDataWrapper::getUV(int uv_index, float *uv)
146 int stride = mVData->getStride(0);
147 if (stride == 0) stride = 2;
149 switch (mVData->getType()) {
150 case COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT:
152 COLLADAFW::ArrayPrimitiveType<float> *values = mVData->getFloatValues();
153 if (values->empty()) return;
154 uv[0] = (*values)[uv_index * stride];
155 uv[1] = (*values)[uv_index * stride + 1];
159 case COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE:
161 COLLADAFW::ArrayPrimitiveType<double> *values = mVData->getDoubleValues();
162 if (values->empty()) return;
163 uv[0] = (float)(*values)[uv_index * stride];
164 uv[1] = (float)(*values)[uv_index * stride + 1];
168 case COLLADAFW::MeshVertexData::DATA_TYPE_UNKNOWN:
170 fprintf(stderr, "MeshImporter.getUV(): unknown data type\n");
174 VCOLDataWrapper::VCOLDataWrapper(COLLADAFW::MeshVertexData& vdata) : mVData(&vdata) {}
176 void VCOLDataWrapper::get_vcol(int v_index, MLoopCol *mloopcol)
178 int stride = mVData->getStride(0);
179 if (stride == 0) stride = 3;
181 switch (mVData->getType()) {
182 case COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT:
184 COLLADAFW::ArrayPrimitiveType<float> *values = mVData->getFloatValues();
185 if (values->empty() || values->getCount() <= (v_index * stride + 2)) return; // xxx need to create an error instead
187 mloopcol->r = unit_float_to_uchar_clamp((*values)[v_index * stride]);
188 mloopcol->g = unit_float_to_uchar_clamp((*values)[v_index * stride + 1]);
189 mloopcol->b = unit_float_to_uchar_clamp((*values)[v_index * stride + 2]);
193 case COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE:
195 COLLADAFW::ArrayPrimitiveType<double> *values = mVData->getDoubleValues();
196 if (values->empty() || values->getCount() <= (v_index * stride + 2)) return; // xxx need to create an error instead
198 mloopcol->r = unit_float_to_uchar_clamp((*values)[v_index * stride]);
199 mloopcol->g = unit_float_to_uchar_clamp((*values)[v_index * stride + 1]);
200 mloopcol->b = unit_float_to_uchar_clamp((*values)[v_index * stride + 2]);
204 fprintf(stderr, "VCOLDataWrapper.getvcol(): unknown data type\n");
209 MeshImporter::MeshImporter(UnitConverter *unitconv, ArmatureImporter *arm, Main *bmain, Scene *sce, ViewLayer *view_layer):
210 unitconverter(unitconv),
213 view_layer(view_layer),
214 armature_importer(arm) {
217 bool MeshImporter::set_poly_indices(MPoly *mpoly, MLoop *mloop, int loop_index, unsigned int *indices, int loop_count)
219 mpoly->loopstart = loop_index;
220 mpoly->totloop = loop_count;
221 bool broken_loop = false;
222 for (int index=0; index < loop_count; index++) {
224 /* Test if loop defines a hole */
226 for (int i = 0; i < index; i++) {
227 if (indices[i] == indices[index]) {
228 // duplicate index -> not good
234 mloop->v = indices[index];
240 void MeshImporter::set_vcol(MLoopCol *mlc, VCOLDataWrapper &vob, int loop_index, COLLADAFW::IndexList &index_list, int count)
243 for (index = 0; index < count; index++, mlc++) {
244 int v_index = index_list.getIndex(index + loop_index);
245 vob.get_vcol(v_index,mlc);
249 void MeshImporter::set_face_uv(MLoopUV *mloopuv, UVDataWrapper &uvs,
250 int start_index, COLLADAFW::IndexList& index_list, int count)
252 // per face vertex indices, this means for quad we have 4 indices, not 8
253 COLLADAFW::UIntValuesArray& indices = index_list.getIndices();
255 for (int index = 0; index < count; index++) {
256 int uv_index = indices[index+start_index];
257 uvs.getUV(uv_index, mloopuv[index].uv);
262 void MeshImporter::print_index_list(COLLADAFW::IndexList& index_list)
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));
268 fprintf(stderr, "\n");
272 bool MeshImporter::is_nice_mesh(COLLADAFW::Mesh *mesh) // checks if mesh has supported primitive types: lines, polylist, triangles, triangle_fans
274 COLLADAFW::MeshPrimitiveArray& prim_arr = mesh->getMeshPrimitives();
276 const std::string &name = bc_get_dae_name(mesh);
278 for (unsigned i = 0; i < prim_arr.getCount(); i++) {
280 COLLADAFW::MeshPrimitive *mp = prim_arr[i];
281 COLLADAFW::MeshPrimitive::PrimitiveType type = mp->getPrimitiveType();
283 const char *type_str = bc_primTypeToStr(type);
285 // OpenCollada passes POLYGONS type for <polylist>
286 if (type == COLLADAFW::MeshPrimitive::POLYLIST || type == COLLADAFW::MeshPrimitive::POLYGONS) {
288 COLLADAFW::Polygons *mpvc = (COLLADAFW::Polygons *)mp;
289 COLLADAFW::Polygons::VertexCountArray& vca = mpvc->getGroupedVerticesVertexCountArray();
292 int nonface_count = 0;
294 for (unsigned int j = 0; j < vca.getCount(); j++) {
296 if (abs(count) < 3) {
305 if (hole_count > 0) {
306 fprintf(stderr, "WARNING: Primitive %s in %s: %d holes not imported (unsupported)\n", type_str, name.c_str(), hole_count);
309 if (nonface_count > 0) {
310 fprintf(stderr, "WARNING: Primitive %s in %s: %d faces with vertex count < 3 (rejected)\n", type_str, name.c_str(), nonface_count);
314 else if (type == COLLADAFW::MeshPrimitive::LINES) {
315 // TODO: Add Checker for line syntax here
318 else if (type != COLLADAFW::MeshPrimitive::TRIANGLES && type != COLLADAFW::MeshPrimitive::TRIANGLE_FANS) {
319 fprintf(stderr, "ERROR: Primitive type %s is not supported.\n", type_str);
327 void MeshImporter::read_vertices(COLLADAFW::Mesh *mesh, Mesh *me)
330 COLLADAFW::MeshVertexData& pos = mesh->getPositions();
335 int stride = pos.getStride(0);
336 if (stride == 0) stride = 3;
338 me->totvert = pos.getFloatValues()->getCount() / stride;
339 me->mvert = (MVert *)CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, me->totvert);
344 for (i = 0, mvert = me->mvert; i < me->totvert; i++, mvert++) {
345 get_vector(mvert->co, pos, i, stride);
350 // =====================================================================
351 // condition 1: The Primitive has normals
352 // condition 2: The number of normals equals the number of faces.
353 // return true if both conditions apply.
354 // return false otherwise.
355 // =====================================================================
356 bool MeshImporter::primitive_has_useable_normals(COLLADAFW::MeshPrimitive *mp) {
358 bool has_useable_normals = false;
360 int normals_count = mp->getNormalIndices().getCount();
361 if (normals_count > 0) {
362 int index_count = mp->getPositionIndices().getCount();
363 if (index_count == normals_count)
364 has_useable_normals = true;
367 "Warning: Number of normals %d is different from the number of vertices %d, skipping normals\n",
368 normals_count, index_count);
372 return has_useable_normals;
376 // =====================================================================
377 // Assume that only TRIANGLES, TRIANGLE_FANS, POLYLIST and POLYGONS
378 // have faces. (to be verified)
379 // =====================================================================
380 bool MeshImporter::primitive_has_faces(COLLADAFW::MeshPrimitive *mp) {
382 bool has_faces = false;
383 int type = mp->getPrimitiveType();
385 case COLLADAFW::MeshPrimitive::TRIANGLES:
386 case COLLADAFW::MeshPrimitive::TRIANGLE_FANS:
387 case COLLADAFW::MeshPrimitive::POLYLIST:
388 case COLLADAFW::MeshPrimitive::POLYGONS:
402 static std::string extract_vcolname(const COLLADAFW::String &collada_id) {
403 std::string colname = collada_id;
404 int spos = colname.find("-mesh-colors-");
405 if (spos != std::string::npos) {
406 colname = colname.substr(spos+13);
412 // =================================================================
413 // Return the number of faces by summing up
414 // the facecounts of the parts.
415 // hint: This is done because mesh->getFacesCount() does
416 // count loose edges as extra faces, which is not what we want here.
417 // =================================================================
418 void MeshImporter::allocate_poly_data(COLLADAFW::Mesh *collada_mesh, Mesh *me)
420 COLLADAFW::MeshPrimitiveArray& prim_arr = collada_mesh->getMeshPrimitives();
421 int total_poly_count = 0;
422 int total_loop_count = 0;
424 // collect edge_count and face_count from all parts
425 for (int i = 0; i < prim_arr.getCount(); i++) {
426 COLLADAFW::MeshPrimitive *mp = prim_arr[i];
427 int type = mp->getPrimitiveType();
429 case COLLADAFW::MeshPrimitive::TRIANGLES:
430 case COLLADAFW::MeshPrimitive::TRIANGLE_FANS:
431 case COLLADAFW::MeshPrimitive::POLYLIST:
432 case COLLADAFW::MeshPrimitive::POLYGONS:
434 COLLADAFW::Polygons *mpvc = (COLLADAFW::Polygons *)mp;
435 size_t prim_poly_count = mpvc->getFaceCount();
437 size_t prim_loop_count = 0;
438 for (int index=0; index < prim_poly_count; index++)
440 int vcount = get_vertex_count(mpvc, index);
442 prim_loop_count += vcount;
446 // TODO: this is a hole and not another polygon!
450 total_loop_count += prim_loop_count;
459 // Add the data containers
460 if (total_poly_count > 0) {
461 me->totpoly = total_poly_count;
462 me->totloop = total_loop_count;
463 me->mpoly = (MPoly *)CustomData_add_layer(&me->pdata, CD_MPOLY, CD_CALLOC, NULL, me->totpoly);
464 me->mloop = (MLoop *)CustomData_add_layer(&me->ldata, CD_MLOOP, CD_CALLOC, NULL, me->totloop);
466 unsigned int totuvset = collada_mesh->getUVCoords().getInputInfosArray().getCount();
467 for (int i = 0; i < totuvset; i++) {
468 if (collada_mesh->getUVCoords().getLength(i) == 0) {
475 for (int i = 0; i < totuvset; i++) {
476 COLLADAFW::MeshVertexData::InputInfos *info = collada_mesh->getUVCoords().getInputInfosArray()[i];
477 COLLADAFW::String &uvname = info->mName;
478 // Allocate space for UV_data
479 CustomData_add_layer_named(&me->ldata, CD_MLOOPUV, CD_DEFAULT, NULL, me->totloop, uvname.c_str());
481 // activate the first uv map
482 me->mloopuv = (MLoopUV *) CustomData_get_layer_n(&me->ldata, CD_MLOOPUV, 0);
485 int totcolset = collada_mesh->getColors().getInputInfosArray().getCount();
487 for (int i = 0; i < totcolset; i++) {
488 COLLADAFW::MeshVertexData::InputInfos *info = collada_mesh->getColors().getInputInfosArray()[i];
489 COLLADAFW::String colname = extract_vcolname(info->mName);
490 CustomData_add_layer_named(&me->ldata,CD_MLOOPCOL,CD_DEFAULT,NULL,me->totloop, colname.c_str());
492 me->mloopcol = (MLoopCol *) CustomData_get_layer_n(&me->ldata, CD_MLOOPCOL, 0);
498 unsigned int MeshImporter::get_vertex_count(COLLADAFW::Polygons *mp, int index) {
499 int type = mp->getPrimitiveType();
502 case COLLADAFW::MeshPrimitive::TRIANGLES:
503 case COLLADAFW::MeshPrimitive::TRIANGLE_FANS:
508 case COLLADAFW::MeshPrimitive::POLYLIST:
509 case COLLADAFW::MeshPrimitive::POLYGONS:
511 result = mp->getGroupedVerticesVertexCountArray()[index];
524 unsigned int MeshImporter::get_loose_edge_count(COLLADAFW::Mesh *mesh) {
525 COLLADAFW::MeshPrimitiveArray& prim_arr = mesh->getMeshPrimitives();
526 int loose_edge_count = 0;
528 // collect edge_count and face_count from all parts
529 for (int i = 0; i < prim_arr.getCount(); i++) {
530 COLLADAFW::MeshPrimitive *mp = prim_arr[i];
531 int type = mp->getPrimitiveType();
533 case COLLADAFW::MeshPrimitive::LINES:
535 size_t prim_totface = mp->getFaceCount();
536 loose_edge_count += prim_totface;
543 return loose_edge_count;
546 // =================================================================
547 // This function is copied from source/blender/editors/mesh/mesh_data.c
549 // TODO: (As discussed with sergey-) :
550 // Maybe move this function to blenderkernel/intern/mesh.c
551 // and add definition to BKE_mesh.c
552 // =================================================================
553 void MeshImporter::mesh_add_edges(Mesh *mesh, int len)
562 totedge = mesh->totedge + len;
564 /* update customdata */
565 CustomData_copy(&mesh->edata, &edata, CD_MASK_MESH, CD_DEFAULT, totedge);
566 CustomData_copy_data(&mesh->edata, &edata, 0, 0, mesh->totedge);
568 if (!CustomData_has_layer(&edata, CD_MEDGE))
569 CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, NULL, totedge);
571 CustomData_free(&mesh->edata, mesh->totedge);
573 BKE_mesh_update_customdata_pointers(mesh, false); /* new edges don't change tessellation */
575 /* set default flags */
576 medge = &mesh->medge[mesh->totedge];
577 for (int i = 0; i < len; i++, medge++)
578 medge->flag = ME_EDGEDRAW | ME_EDGERENDER | SELECT;
580 mesh->totedge = totedge;
583 // =================================================================
584 // Read all loose edges.
585 // Important: This function assumes that all edges from existing
586 // faces have already been generated and added to me->medge
587 // So this function MUST be called after read_faces() (see below)
588 // =================================================================
589 void MeshImporter::read_lines(COLLADAFW::Mesh *mesh, Mesh *me)
591 unsigned int loose_edge_count = get_loose_edge_count(mesh);
592 if (loose_edge_count > 0) {
594 unsigned int face_edge_count = me->totedge;
595 /* unsigned int total_edge_count = loose_edge_count + face_edge_count; */ /* UNUSED */
597 mesh_add_edges(me, loose_edge_count);
598 MEdge *med = me->medge + face_edge_count;
600 COLLADAFW::MeshPrimitiveArray& prim_arr = mesh->getMeshPrimitives();
602 for (int index = 0; index < prim_arr.getCount(); index++) {
603 COLLADAFW::MeshPrimitive *mp = prim_arr[index];
605 int type = mp->getPrimitiveType();
606 if (type == COLLADAFW::MeshPrimitive::LINES) {
607 unsigned int edge_count = mp->getFaceCount();
608 unsigned int *indices = mp->getPositionIndices().getData();
610 for (int j = 0; j < edge_count; j++, med++) {
613 med->flag |= ME_LOOSEEDGE;
614 med->v1 = indices[2 * j];
615 med->v2 = indices[2 * j + 1];
624 // =======================================================================
625 // Read all faces from TRIANGLES, TRIANGLE_FANS, POLYLIST, POLYGON
626 // Important: This function MUST be called before read_lines()
627 // Otherwise we will loose all edges from faces (see read_lines() above)
629 // TODO: import uv set names
630 // ========================================================================
631 void MeshImporter::read_polys(COLLADAFW::Mesh *collada_mesh, Mesh *me)
635 allocate_poly_data(collada_mesh, me);
637 UVDataWrapper uvs(collada_mesh->getUVCoords());
638 VCOLDataWrapper vcol(collada_mesh->getColors());
640 MPoly *mpoly = me->mpoly;
641 MLoop *mloop = me->mloop;
644 MaterialIdPrimitiveArrayMap mat_prim_map;
646 COLLADAFW::MeshPrimitiveArray& prim_arr = collada_mesh->getMeshPrimitives();
647 COLLADAFW::MeshVertexData& nor = collada_mesh->getNormals();
649 for (i = 0; i < prim_arr.getCount(); i++) {
651 COLLADAFW::MeshPrimitive *mp = prim_arr[i];
654 size_t prim_totpoly = mp->getFaceCount();
655 unsigned int *position_indices = mp->getPositionIndices().getData();
656 unsigned int *normal_indices = mp->getNormalIndices().getData();
659 bool mp_has_normals = primitive_has_useable_normals(mp);
660 bool mp_has_faces = primitive_has_faces(mp);
662 int collada_meshtype = mp->getPrimitiveType();
664 // since we cannot set mpoly->mat_nr here, we store a portion of me->mpoly in Primitive
665 Primitive prim = {mpoly, 0};
667 // If MeshPrimitive is TRIANGLE_FANS we split it into triangles
668 // The first trifan vertex will be the first vertex in every triangle
669 // XXX The proper function of TRIANGLE_FANS is not tested!!!
670 // XXX In particular the handling of the normal_indices looks very wrong to me
671 if (collada_meshtype == COLLADAFW::MeshPrimitive::TRIANGLE_FANS) {
672 unsigned grouped_vertex_count = mp->getGroupedVertexElementsCount();
673 for (unsigned int group_index = 0; group_index < grouped_vertex_count; group_index++) {
674 unsigned int first_vertex = position_indices[0]; // Store first trifan vertex
675 unsigned int first_normal = normal_indices[0]; // Store first trifan vertex normal
676 unsigned int vertex_count = mp->getGroupedVerticesVertexCount(group_index);
678 for (unsigned int vertex_index = 0; vertex_index < vertex_count - 2; vertex_index++) {
679 // For each triangle store indices of its 3 vertices
680 unsigned int triangle_vertex_indices[3] = {first_vertex, position_indices[1], position_indices[2]};
681 set_poly_indices(mpoly, mloop, loop_index, triangle_vertex_indices, 3);
683 if (mp_has_normals) { // vertex normals, same inplementation as for the triangles
684 // the same for vertces normals
685 unsigned int vertex_normal_indices[3] = {first_normal, normal_indices[1], normal_indices[2]};
686 if (!is_flat_face(vertex_normal_indices, nor, 3))
687 mpoly->flag |= ME_SMOOTH;
698 // Moving cursor to the next triangle fan.
702 position_indices += 2;
706 if (collada_meshtype == COLLADAFW::MeshPrimitive::POLYLIST ||
707 collada_meshtype == COLLADAFW::MeshPrimitive::POLYGONS ||
708 collada_meshtype == COLLADAFW::MeshPrimitive::TRIANGLES)
710 COLLADAFW::Polygons *mpvc = (COLLADAFW::Polygons *)mp;
711 unsigned int start_index = 0;
713 COLLADAFW::IndexListArray& index_list_array_uvcoord = mp->getUVCoordIndicesArray();
714 COLLADAFW::IndexListArray& index_list_array_vcolor = mp->getColorIndicesArray();
716 int invalid_loop_holes = 0;
717 for (unsigned int j = 0; j < prim_totpoly; j++) {
719 // Vertices in polygon:
720 int vcount = get_vertex_count(mpvc, j);
722 continue; // TODO: add support for holes
725 bool broken_loop = set_poly_indices(mpoly, mloop, loop_index, position_indices, vcount);
728 invalid_loop_holes += 1;
731 for (unsigned int uvset_index = 0; uvset_index < index_list_array_uvcoord.getCount(); uvset_index++) {
732 // get mtface by face index and uv set index
733 COLLADAFW::IndexList& index_list = *index_list_array_uvcoord[uvset_index];
734 MLoopUV *mloopuv = (MLoopUV *)CustomData_get_layer_named(&me->ldata, CD_MLOOPUV, index_list.getName().c_str());
735 if (mloopuv == NULL) {
736 fprintf(stderr, "Collada import: Mesh [%s] : Unknown reference to TEXCOORD [#%s].\n", me->id.name, index_list.getName().c_str() );
739 set_face_uv(mloopuv+loop_index, uvs, start_index, *index_list_array_uvcoord[uvset_index], vcount);
743 if (mp_has_normals) {
744 if (!is_flat_face(normal_indices, nor, vcount))
745 mpoly->flag |= ME_SMOOTH;
749 if (mp->hasColorIndices()) {
750 int vcolor_count = index_list_array_vcolor.getCount();
752 for (unsigned int vcolor_index = 0; vcolor_index < vcolor_count; vcolor_index++) {
754 COLLADAFW::IndexList& color_index_list = *mp->getColorIndices(vcolor_index);
755 COLLADAFW::String colname = extract_vcolname(color_index_list.getName());
756 MLoopCol *mloopcol = (MLoopCol *)CustomData_get_layer_named(&me->ldata, CD_MLOOPCOL, colname.c_str());
757 if (mloopcol == NULL) {
758 fprintf(stderr, "Collada import: Mesh [%s] : Unknown reference to VCOLOR [#%s].\n", me->id.name, color_index_list.getName().c_str());
761 set_vcol(mloopcol + loop_index, vcol, start_index, color_index_list, vcount);
768 loop_index += vcount;
769 start_index += vcount;
773 normal_indices += vcount;
775 position_indices += vcount;
778 if (invalid_loop_holes > 0)
780 fprintf(stderr, "Collada import: Mesh [%s] : contains %d unsupported loops (holes).\n", me->id.name, invalid_loop_holes);
784 else if (collada_meshtype == COLLADAFW::MeshPrimitive::LINES) {
785 continue; // read the lines later after all the rest is done
789 mat_prim_map[mp->getMaterialId()].push_back(prim);
794 geom_uid_mat_mapping_map[collada_mesh->getUniqueId()] = mat_prim_map;
797 void MeshImporter::get_vector(float v[3], COLLADAFW::MeshVertexData& arr, int i, int stride)
801 switch (arr.getType()) {
802 case COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT:
804 COLLADAFW::ArrayPrimitiveType<float> *values = arr.getFloatValues();
805 if (values->empty()) return;
807 v[0] = (*values)[i++];
808 v[1] = (*values)[i++];
818 case COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE:
820 COLLADAFW::ArrayPrimitiveType<double> *values = arr.getDoubleValues();
821 if (values->empty()) return;
823 v[0] = (float)(*values)[i++];
824 v[1] = (float)(*values)[i++];
826 v[2] = (float)(*values)[i];
838 bool MeshImporter::is_flat_face(unsigned int *nind, COLLADAFW::MeshVertexData& nor, int count)
842 get_vector(a, nor, *nind, 3);
847 for (int i = 1; i < count; i++, nind++) {
848 get_vector(b, nor, *nind, 3);
851 float dp = dot_v3v3(a, b);
853 if (dp < 0.99999f || dp > 1.00001f)
860 Object *MeshImporter::get_object_by_geom_uid(const COLLADAFW::UniqueId& geom_uid)
862 if (uid_object_map.find(geom_uid) != uid_object_map.end())
863 return uid_object_map[geom_uid];
867 Mesh *MeshImporter::get_mesh_by_geom_uid(const COLLADAFW::UniqueId& mesh_uid)
869 if (uid_mesh_map.find(mesh_uid) != uid_mesh_map.end())
870 return uid_mesh_map[mesh_uid];
874 std::string *MeshImporter::get_geometry_name(const std::string &mesh_name)
876 if (this->mesh_geom_map.find(mesh_name) != this->mesh_geom_map.end())
877 return &this->mesh_geom_map[mesh_name];
882 * this function checks if both objects have the same
883 * materials assigned to Object (in the same order)
884 * returns true if condition matches, otherwise false;
886 static bool bc_has_same_material_configuration(Object *ob1, Object *ob2)
888 if (ob1->totcol != ob2->totcol) return false; // not same number of materials
889 if (ob1->totcol == 0) return false; // no material at all
891 for (int index=0; index < ob1->totcol; index++) {
892 if (ob1->matbits[index] != ob2->matbits[index]) return false; // shouldn't happen
893 if (ob1->matbits[index] == 0) return false; // shouldn't happen
894 if (ob1->mat[index] != ob2->mat[index]) return false; // different material assignment
902 * Caution here: This code assumes that all materials are assigned to Object
903 * and no material is assigned to Data.
904 * That is true right after the objects have been imported.
907 static void bc_copy_materials_to_data(Object *ob, Mesh *me)
909 for (int index = 0; index < ob->totcol; index++) {
910 ob->matbits[index] = 0;
911 me->mat[index] = ob->mat[index];
917 * Remove all references to materials from the object
920 static void bc_remove_materials_from_object(Object *ob, Mesh *me)
922 for (int index = 0; index < ob->totcol; index++) {
923 ob->matbits[index] = 0;
924 ob->mat[index] = NULL;
929 * Returns the list of Users of the given Mesh object.
930 * Note: This function uses the object user flag to control
931 * which objects have already been processed.
933 std::vector<Object *> MeshImporter::get_all_users_of(Mesh *reference_mesh)
935 std::vector<Object *> mesh_users;
936 for (std::vector<Object *>::iterator it = imported_objects.begin();
937 it != imported_objects.end(); ++it)
940 if (bc_is_marked(ob)) {
942 Mesh *me = (Mesh *) ob->data;
943 if (me == reference_mesh)
944 mesh_users.push_back(ob);
952 * During import all materials have been assigned to Object.
953 * Now we iterate over the imported objects and optimize
954 * the assignments as follows:
956 * for each imported geometry:
957 * if number of users is 1:
958 * get the user (object)
959 * move the materials from Object to Data
961 * determine which materials are assigned to the first user
962 * check if all other users have the same materials in the same order
963 * if the check is positive:
964 * Add the materials of the first user to the geometry
965 * adjust all other users accordingly.
968 void MeshImporter::optimize_material_assignements()
970 for (std::vector<Object *>::iterator it = imported_objects.begin();
971 it != imported_objects.end(); ++it)
974 Mesh *me = (Mesh *) ob->data;
976 bc_copy_materials_to_data(ob, me);
977 bc_remove_materials_from_object(ob, me);
980 else if (me->id.us > 1)
982 bool can_move = true;
983 std::vector<Object *> mesh_users = get_all_users_of(me);
984 if (mesh_users.size() > 1)
986 Object *ref_ob = mesh_users[0];
987 for (int index = 1; index < mesh_users.size(); index++) {
988 if (!bc_has_same_material_configuration(ref_ob, mesh_users[index])) {
994 bc_copy_materials_to_data(ref_ob, me);
995 for (int index = 0; index < mesh_users.size(); index++) {
996 Object *object = mesh_users[index];
997 bc_remove_materials_from_object(object, me);
998 bc_remove_mark(object);
1007 * We do not know in advance which objects will share geometries.
1008 * And we do not know either if the objects which share geometries
1009 * come along with different materials. So we first create the objects
1010 * and assign the materials to Object, then in a later cleanup we decide
1011 * which materials shall be moved to the created geometries. Also see
1012 * optimize_material_assignements() above.
1014 void MeshImporter::assign_material_to_geom(
1015 COLLADAFW::MaterialBinding cmaterial,
1016 std::map<COLLADAFW::UniqueId, Material *>& uid_material_map,
1017 Object *ob, const COLLADAFW::UniqueId *geom_uid,
1020 const COLLADAFW::UniqueId& ma_uid = cmaterial.getReferencedMaterial();
1022 // do we know this material?
1023 if (uid_material_map.find(ma_uid) == uid_material_map.end()) {
1025 fprintf(stderr, "Cannot find material by UID.\n");
1029 // first time we get geom_uid, ma_uid pair. Save for later check.
1030 materials_mapped_to_geom.insert(std::pair<COLLADAFW::UniqueId, COLLADAFW::UniqueId>(*geom_uid, ma_uid));
1032 Material *ma = uid_material_map[ma_uid];
1034 // Attention! This temporarily assigns material to object on purpose!
1037 assign_material(m_bmain, ob, ma, mat_index + 1, BKE_MAT_ASSIGN_OBJECT);
1039 MaterialIdPrimitiveArrayMap& mat_prim_map = geom_uid_mat_mapping_map[*geom_uid];
1040 COLLADAFW::MaterialId mat_id = cmaterial.getMaterialId();
1042 // assign material indices to mesh faces
1043 if (mat_prim_map.find(mat_id) != mat_prim_map.end()) {
1045 std::vector<Primitive>& prims = mat_prim_map[mat_id];
1047 std::vector<Primitive>::iterator it;
1049 for (it = prims.begin(); it != prims.end(); it++) {
1050 Primitive& prim = *it;
1051 MPoly *mpoly = prim.mpoly;
1053 for (int i = 0; i < prim.totpoly; i++, mpoly++) {
1054 mpoly->mat_nr = mat_index;
1060 Object *MeshImporter::create_mesh_object(COLLADAFW::Node *node, COLLADAFW::InstanceGeometry *geom,
1062 std::map<COLLADAFW::UniqueId, Material *>& uid_material_map)
1064 const COLLADAFW::UniqueId *geom_uid = &geom->getInstanciatedObjectId();
1066 // check if node instantiates controller or geometry
1069 geom_uid = armature_importer->get_geometry_uid(*geom_uid);
1072 fprintf(stderr, "Couldn't find a mesh UID by controller's UID.\n");
1078 if (uid_mesh_map.find(*geom_uid) == uid_mesh_map.end()) {
1079 // this could happen if a mesh was not created
1080 // (e.g. if it contains unsupported geometry)
1081 fprintf(stderr, "Couldn't find a mesh by UID.\n");
1085 if (!uid_mesh_map[*geom_uid]) return NULL;
1088 const std::string& id = node->getName().size() ? node->getName() : node->getOriginalId();
1089 const char *name = (id.length()) ? id.c_str() : NULL;
1092 Object *ob = bc_add_object(m_bmain, scene, view_layer, OB_MESH, name);
1093 bc_set_mark(ob); // used later for material assignment optimization
1096 // store object pointer for ArmatureImporter
1097 uid_object_map[*geom_uid] = ob;
1098 imported_objects.push_back(ob);
1100 // replace ob->data freeing the old one
1101 Mesh *old_mesh = (Mesh *)ob->data;
1102 Mesh *new_mesh = uid_mesh_map[*geom_uid];
1104 BKE_mesh_assign_object(m_bmain, ob, new_mesh);
1105 BKE_mesh_calc_normals(new_mesh);
1107 id_us_plus(&old_mesh->id); /* Because BKE_mesh_assign_object would have already decreased it... */
1108 BKE_id_free_us(m_bmain, old_mesh);
1110 COLLADAFW::MaterialBindingArray& mat_array =
1111 geom->getMaterialBindings();
1113 // loop through geom's materials
1114 for (unsigned int i = 0; i < mat_array.getCount(); i++) {
1116 if (mat_array[i].getReferencedMaterial().isValid()) {
1117 assign_material_to_geom(
1118 mat_array[i], uid_material_map, ob, geom_uid,
1122 fprintf(stderr, "invalid referenced material for %s\n", mat_array[i].getName().c_str());
1126 // clean up the mesh
1127 BKE_mesh_validate((Mesh *)ob->data, false, false);
1132 // create a mesh storing a pointer in a map so it can be retrieved later by geometry UID
1133 bool MeshImporter::write_geometry(const COLLADAFW::Geometry *geom)
1136 if (geom->getType() != COLLADAFW::Geometry::GEO_TYPE_MESH) {
1137 // TODO: report warning
1138 fprintf(stderr, "Mesh type %s is not supported\n", bc_geomTypeToStr(geom->getType()));
1142 COLLADAFW::Mesh *mesh = (COLLADAFW::Mesh *)geom;
1144 if (!is_nice_mesh(mesh)) {
1145 fprintf(stderr, "Ignoring mesh %s\n", bc_get_dae_name(mesh).c_str());
1149 const std::string& str_geom_id = mesh->getName().size() ? mesh->getName() : mesh->getOriginalId();
1150 Mesh *me = BKE_mesh_add(m_bmain, (char *)str_geom_id.c_str());
1151 id_us_min(&me->id); // is already 1 here, but will be set later in BKE_mesh_assign_object
1153 // store the Mesh pointer to link it later with an Object
1154 // mesh_geom_map needed to map mesh to its geometry name (for shape key naming)
1155 this->uid_mesh_map[mesh->getUniqueId()] = me;
1156 this->mesh_geom_map[std::string(me->id.name)] = str_geom_id;
1158 read_vertices(mesh, me);
1159 read_polys(mesh, me);
1160 BKE_mesh_calc_edges(me, false, false);
1161 // read_lines() must be called after the face edges have been generated.
1162 // Otherwise the loose edges will be silently deleted again.
1163 read_lines(mesh, me);