Blender V2.61 - r43446

MeshImporter.cpp

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * Contributor(s): Chingiz Dyussenov, Arystanbek Dyussenov, Nathan Letwory.
00019  *
00020  * ***** END GPL LICENSE BLOCK *****
00021  */
00022 
00028 #include <algorithm>
00029 
00030 #if !defined(WIN32) || defined(FREE_WINDOWS)
00031 #include <iostream>
00032 #endif
00033 
00034 /* COLLADABU_ASSERT, may be able to remove later */
00035 #include "COLLADABUPlatform.h"
00036 
00037 #include "COLLADAFWMeshPrimitive.h"
00038 #include "COLLADAFWMeshVertexData.h"
00039 #include "COLLADAFWPolygons.h"
00040 
00041 extern "C" {
00042 #include "BKE_blender.h"
00043 #include "BKE_customdata.h"
00044 #include "BKE_displist.h"
00045 #include "BKE_global.h"
00046 #include "BKE_library.h"
00047 #include "BKE_main.h"
00048 #include "BKE_material.h"
00049 #include "BKE_mesh.h"
00050 #include "BKE_object.h"
00051 
00052 #include "BLI_listbase.h"
00053 #include "BLI_math.h"
00054 #include "BLI_string.h"
00055 
00056 #include "MEM_guardedalloc.h"
00057 }
00058 
00059 #include "ArmatureImporter.h"
00060 #include "MeshImporter.h"
00061 #include "collada_utils.h"
00062 
00063 // get node name, or fall back to original id if not present (name is optional)
00064 template<class T>
00065 static const char *bc_get_dae_name(T *node)
00066 {
00067     const std::string& name = node->getName();
00068     return name.size() ? name.c_str() : node->getOriginalId().c_str();
00069 }
00070 
00071 static const char *bc_primTypeToStr(COLLADAFW::MeshPrimitive::PrimitiveType type)
00072 {
00073     switch (type) {
00074     case COLLADAFW::MeshPrimitive::LINES:
00075         return "LINES";
00076     case COLLADAFW::MeshPrimitive::LINE_STRIPS:
00077         return "LINESTRIPS";
00078     case COLLADAFW::MeshPrimitive::POLYGONS:
00079         return "POLYGONS";
00080     case COLLADAFW::MeshPrimitive::POLYLIST:
00081         return "POLYLIST";
00082     case COLLADAFW::MeshPrimitive::TRIANGLES:
00083         return "TRIANGLES";
00084     case COLLADAFW::MeshPrimitive::TRIANGLE_FANS:
00085         return "TRIANGLE_FANS";
00086     case COLLADAFW::MeshPrimitive::TRIANGLE_STRIPS:
00087         return "TRIANGLE_FANS";
00088     case COLLADAFW::MeshPrimitive::POINTS:
00089         return "POINTS";
00090     case COLLADAFW::MeshPrimitive::UNDEFINED_PRIMITIVE_TYPE:
00091         return "UNDEFINED_PRIMITIVE_TYPE";
00092     }
00093     return "UNKNOWN";
00094 }
00095 
00096 static const char *bc_geomTypeToStr(COLLADAFW::Geometry::GeometryType type)
00097 {
00098     switch (type) {
00099     case COLLADAFW::Geometry::GEO_TYPE_MESH:
00100         return "MESH";
00101     case COLLADAFW::Geometry::GEO_TYPE_SPLINE:
00102         return "SPLINE";
00103     case COLLADAFW::Geometry::GEO_TYPE_CONVEX_MESH:
00104         return "CONVEX_MESH";
00105     case COLLADAFW::Geometry::GEO_TYPE_UNKNOWN:
00106     default:
00107         return "UNKNOWN";
00108     }
00109 }
00110 
00111 
00112 UVDataWrapper::UVDataWrapper(COLLADAFW::MeshVertexData& vdata) : mVData(&vdata)
00113 {}
00114 
00115 #ifdef COLLADA_DEBUG
00116 void WVDataWrapper::print()
00117 {
00118     fprintf(stderr, "UVs:\n");
00119     switch(mVData->getType()) {
00120     case COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT:
00121         {
00122             COLLADAFW::ArrayPrimitiveType<float>* values = mVData->getFloatValues();
00123             if (values->getCount()) {
00124                 for (int i = 0; i < values->getCount(); i += 2) {
00125                     fprintf(stderr, "%.1f, %.1f\n", (*values)[i], (*values)[i+1]);
00126                 }
00127             }
00128         }
00129         break;
00130     case COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE:
00131         {
00132             COLLADAFW::ArrayPrimitiveType<double>* values = mVData->getDoubleValues();
00133             if (values->getCount()) {
00134                 for (int i = 0; i < values->getCount(); i += 2) {
00135                     fprintf(stderr, "%.1f, %.1f\n", (float)(*values)[i], (float)(*values)[i+1]);
00136                 }
00137             }
00138         }
00139         break;
00140     }
00141     fprintf(stderr, "\n");
00142 }
00143 #endif
00144 
00145 void UVDataWrapper::getUV(int uv_index, float *uv)
00146 {
00147     int stride = mVData->getStride(0);
00148     if(stride==0) stride = 2;
00149 
00150     switch(mVData->getType()) {
00151     case COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT:
00152         {
00153             COLLADAFW::ArrayPrimitiveType<float>* values = mVData->getFloatValues();
00154             if (values->empty()) return;
00155             uv[0] = (*values)[uv_index*stride];
00156             uv[1] = (*values)[uv_index*stride + 1];
00157             
00158         }
00159         break;
00160     case COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE:
00161         {
00162             COLLADAFW::ArrayPrimitiveType<double>* values = mVData->getDoubleValues();
00163             if (values->empty()) return;
00164             uv[0] = (float)(*values)[uv_index*stride];
00165             uv[1] = (float)(*values)[uv_index*stride + 1];
00166             
00167         }
00168         break;
00169     case COLLADAFW::MeshVertexData::DATA_TYPE_UNKNOWN:
00170     default:
00171         fprintf(stderr, "MeshImporter.getUV(): unknown data type\n");
00172     }
00173 }
00174 
00175 void MeshImporter::set_face_indices(MFace *mface, unsigned int *indices, bool quad)
00176 {
00177     mface->v1 = indices[0];
00178     mface->v2 = indices[1];
00179     mface->v3 = indices[2];
00180     if (quad) mface->v4 = indices[3];
00181     else mface->v4 = 0;
00182 #ifdef COLLADA_DEBUG
00183     // fprintf(stderr, "%u, %u, %u \n", indices[0], indices[1], indices[2]);
00184 #endif
00185 }
00186 
00187 // not used anymore, test_index_face from blenkernel is better
00188 #if 0
00189 // change face indices order so that v4 is not 0
00190 void MeshImporter::rotate_face_indices(MFace *mface)
00191 {
00192     mface->v4 = mface->v1;
00193     mface->v1 = mface->v2;
00194     mface->v2 = mface->v3;
00195     mface->v3 = 0;
00196 }
00197 #endif
00198 
00199 void MeshImporter::set_face_uv(MTFace *mtface, UVDataWrapper &uvs,
00200                  COLLADAFW::IndexList& index_list, unsigned int *tris_indices)
00201 {
00202     // per face vertex indices, this means for quad we have 4 indices, not 8
00203     COLLADAFW::UIntValuesArray& indices = index_list.getIndices();
00204 
00205     uvs.getUV(indices[tris_indices[0]], mtface->uv[0]);
00206     uvs.getUV(indices[tris_indices[1]], mtface->uv[1]);
00207     uvs.getUV(indices[tris_indices[2]], mtface->uv[2]);
00208 }
00209 
00210 void MeshImporter::set_face_uv(MTFace *mtface, UVDataWrapper &uvs,
00211                 COLLADAFW::IndexList& index_list, int index, bool quad)
00212 {
00213     // per face vertex indices, this means for quad we have 4 indices, not 8
00214     COLLADAFW::UIntValuesArray& indices = index_list.getIndices();
00215 
00216     uvs.getUV(indices[index + 0], mtface->uv[0]);
00217     uvs.getUV(indices[index + 1], mtface->uv[1]);
00218     uvs.getUV(indices[index + 2], mtface->uv[2]);
00219 
00220     if (quad) uvs.getUV(indices[index + 3], mtface->uv[3]);
00221 
00222 #ifdef COLLADA_DEBUG
00223     if (quad) {
00224         fprintf(stderr, "face uv:\n"
00225                 "((%d, %d, %d, %d))\n"
00226                 "((%.1f, %.1f), (%.1f, %.1f), (%.1f, %.1f), (%.1f, %.1f))\n",
00227 
00228                 indices[index + 0],
00229                 indices[index + 1],
00230                 indices[index + 2],
00231                 indices[index + 3],
00232 
00233                 mtface->uv[0][0], mtface->uv[0][1],
00234                 mtface->uv[1][0], mtface->uv[1][1],
00235                 mtface->uv[2][0], mtface->uv[2][1],
00236                 mtface->uv[3][0], mtface->uv[3][1]);
00237     }
00238     else {
00239         fprintf(stderr, "face uv:\n"
00240                 "((%d, %d, %d))\n"
00241                 "((%.1f, %.1f), (%.1f, %.1f), (%.1f, %.1f))\n",
00242 
00243                 indices[index + 0],
00244                 indices[index + 1],
00245                 indices[index + 2],
00246 
00247                 mtface->uv[0][0], mtface->uv[0][1],
00248                 mtface->uv[1][0], mtface->uv[1][1],
00249                 mtface->uv[2][0], mtface->uv[2][1]);
00250     }
00251 #endif
00252 }
00253 
00254 #ifdef COLLADA_DEBUG
00255 void MeshImporter::print_index_list(COLLADAFW::IndexList& index_list)
00256 {
00257     fprintf(stderr, "Index list for \"%s\":\n", index_list.getName().c_str());
00258     for (int i = 0; i < index_list.getIndicesCount(); i += 2) {
00259         fprintf(stderr, "%u, %u\n", index_list.getIndex(i), index_list.getIndex(i + 1));
00260     }
00261     fprintf(stderr, "\n");
00262 }
00263 #endif
00264 
00265 bool MeshImporter::is_nice_mesh(COLLADAFW::Mesh *mesh)  // checks if mesh has supported primitive types: polylist, triangles, triangle_fans
00266 {
00267     COLLADAFW::MeshPrimitiveArray& prim_arr = mesh->getMeshPrimitives();
00268 
00269     const char *name = bc_get_dae_name(mesh);
00270     
00271     for (unsigned i = 0; i < prim_arr.getCount(); i++) {
00272         
00273         COLLADAFW::MeshPrimitive *mp = prim_arr[i];
00274         COLLADAFW::MeshPrimitive::PrimitiveType type = mp->getPrimitiveType();
00275 
00276         const char *type_str = bc_primTypeToStr(type);
00277         
00278         // OpenCollada passes POLYGONS type for <polylist>
00279         if (type == COLLADAFW::MeshPrimitive::POLYLIST || type == COLLADAFW::MeshPrimitive::POLYGONS) {
00280 
00281             COLLADAFW::Polygons *mpvc = (COLLADAFW::Polygons*)mp;
00282             COLLADAFW::Polygons::VertexCountArray& vca = mpvc->getGroupedVerticesVertexCountArray();
00283             
00284             for(unsigned int j = 0; j < vca.getCount(); j++){
00285                 int count = vca[j];
00286                 if (count < 3) {
00287                     fprintf(stderr, "Primitive %s in %s has at least one face with vertex count < 3\n",
00288                             type_str, name);
00289                     return false;
00290                 }
00291             }
00292                 
00293         }
00294         else if(type != COLLADAFW::MeshPrimitive::TRIANGLES && type!= COLLADAFW::MeshPrimitive::TRIANGLE_FANS) {
00295             fprintf(stderr, "Primitive type %s is not supported.\n", type_str);
00296             return false;
00297         }
00298     }
00299     
00300     if (mesh->getPositions().empty()) {
00301         fprintf(stderr, "Mesh %s has no vertices.\n", name);
00302         return false;
00303     }
00304 
00305     return true;
00306 }
00307 
00308 void MeshImporter::read_vertices(COLLADAFW::Mesh *mesh, Mesh *me)
00309 {
00310     // vertices
00311     COLLADAFW::MeshVertexData& pos = mesh->getPositions();
00312     int stride = pos.getStride(0);
00313     if(stride==0) stride = 3;
00314     
00315     me->totvert = mesh->getPositions().getFloatValues()->getCount() / stride;
00316     me->mvert = (MVert*)CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, me->totvert);
00317 
00318     MVert *mvert;
00319     int i;
00320 
00321     for (i = 0, mvert = me->mvert; i < me->totvert; i++, mvert++) {
00322         get_vector(mvert->co, pos, i, stride);
00323     }
00324 }
00325 
00326 int MeshImporter::triangulate_poly(unsigned int *indices, int totvert, MVert *verts, std::vector<unsigned int>& tri)
00327 {
00328     ListBase dispbase;
00329     DispList *dl;
00330     float *vert;
00331     int i = 0;
00332     
00333     dispbase.first = dispbase.last = NULL;
00334     
00335     dl = (DispList*)MEM_callocN(sizeof(DispList), "poly disp");
00336     dl->nr = totvert;
00337     dl->type = DL_POLY;
00338     dl->parts = 1;
00339     dl->verts = vert = (float*)MEM_callocN(totvert * 3 * sizeof(float), "poly verts");
00340     dl->index = (int*)MEM_callocN(sizeof(int) * 3 * totvert, "dl index");
00341 
00342     BLI_addtail(&dispbase, dl);
00343     
00344     for (i = 0; i < totvert; i++) {
00345         copy_v3_v3(vert, verts[indices[i]].co);
00346         vert += 3;
00347     }
00348     
00349     filldisplist(&dispbase, &dispbase, 0);
00350 
00351     int tottri = 0;
00352     dl= (DispList*)dispbase.first;
00353 
00354     if (dl->type == DL_INDEX3) {
00355         tottri = dl->parts;
00356 
00357         int *index = dl->index;
00358         for (i= 0; i < tottri; i++) {
00359             int t[3]= {*index, *(index + 1), *(index + 2)};
00360 
00361             std::sort(t, t + 3);
00362 
00363             tri.push_back(t[0]);
00364             tri.push_back(t[1]);
00365             tri.push_back(t[2]);
00366 
00367             index += 3;
00368         }
00369     }
00370 
00371     freedisplist(&dispbase);
00372 
00373     return tottri;
00374 }
00375 
00376 int MeshImporter::count_new_tris(COLLADAFW::Mesh *mesh, Mesh *me)
00377 {
00378     COLLADAFW::MeshPrimitiveArray& prim_arr = mesh->getMeshPrimitives();
00379     unsigned int i;
00380     int tottri = 0;
00381     
00382     for (i = 0; i < prim_arr.getCount(); i++) {
00383         
00384         COLLADAFW::MeshPrimitive *mp = prim_arr[i];
00385         int type = mp->getPrimitiveType();
00386         size_t prim_totface = mp->getFaceCount();
00387         unsigned int *indices = mp->getPositionIndices().getData();
00388         
00389         if (type == COLLADAFW::MeshPrimitive::POLYLIST ||
00390             type == COLLADAFW::MeshPrimitive::POLYGONS) {
00391             
00392             COLLADAFW::Polygons *mpvc = (COLLADAFW::Polygons*)mp;
00393             COLLADAFW::Polygons::VertexCountArray& vcounta = mpvc->getGroupedVerticesVertexCountArray();
00394             
00395             for (unsigned int j = 0; j < prim_totface; j++) {
00396                 int vcount = vcounta[j];
00397                 
00398                 if (vcount > 4) {
00399                     std::vector<unsigned int> tri;
00400                     
00401                     // tottri += triangulate_poly(indices, vcount, me->mvert, tri) - 1; // XXX why - 1?!
00402                     tottri += triangulate_poly(indices, vcount, me->mvert, tri);
00403                 }
00404 
00405                 indices += vcount;
00406             }
00407         }
00408     }
00409     return tottri;
00410 }
00411 
00412 // TODO: import uv set names
00413 void MeshImporter::read_faces(COLLADAFW::Mesh *mesh, Mesh *me, int new_tris) //TODO:: Refactor. Possibly replace by iterators
00414 {
00415     unsigned int i;
00416     
00417     // allocate faces
00418     me->totface = mesh->getFacesCount() + new_tris;
00419     me->mface = (MFace*)CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, NULL, me->totface);
00420     
00421     // allocate UV Maps
00422     unsigned int totuvset = mesh->getUVCoords().getInputInfosArray().getCount();
00423 
00424     for (i = 0; i < totuvset; i++) {
00425         if (mesh->getUVCoords().getLength(i) == 0) {
00426             totuvset = 0;
00427             break;
00428         }
00429     }
00430 
00431     for (i = 0; i < totuvset; i++) {
00432         COLLADAFW::MeshVertexData::InputInfos *info = mesh->getUVCoords().getInputInfosArray()[i];
00433         CustomData_add_layer_named(&me->fdata, CD_MTFACE, CD_CALLOC, NULL, me->totface, info->mName.c_str());
00434         //this->set_layername_map[i] = CustomData_get_layer_name(&me->fdata, CD_MTFACE, i);
00435     }
00436 
00437     // activate the first uv map
00438     if (totuvset) me->mtface = (MTFace*)CustomData_get_layer_n(&me->fdata, CD_MTFACE, 0);
00439 
00440     UVDataWrapper uvs(mesh->getUVCoords());
00441 
00442 #ifdef COLLADA_DEBUG
00443     // uvs.print();
00444 #endif
00445 
00446     MFace *mface = me->mface;
00447 
00448     MaterialIdPrimitiveArrayMap mat_prim_map;
00449 
00450     int face_index = 0;
00451 
00452     COLLADAFW::MeshPrimitiveArray& prim_arr = mesh->getMeshPrimitives();
00453 
00454     bool has_normals = mesh->hasNormals();
00455     COLLADAFW::MeshVertexData& nor = mesh->getNormals();
00456 
00457     for (i = 0; i < prim_arr.getCount(); i++) {
00458         
00459         COLLADAFW::MeshPrimitive *mp = prim_arr[i];
00460 
00461         // faces
00462         size_t prim_totface = mp->getFaceCount();
00463         unsigned int *indices = mp->getPositionIndices().getData();
00464         unsigned int *nind = mp->getNormalIndices().getData();
00465 
00466         if (has_normals && mp->getPositionIndices().getCount() != mp->getNormalIndices().getCount()) {
00467             fprintf(stderr, "Warning: Number of normals is different from the number of vertcies, skipping normals\n");
00468             has_normals = false;
00469         }
00470 
00471         unsigned int j, k;
00472         int type = mp->getPrimitiveType();
00473         int index = 0;
00474         
00475         // since we cannot set mface->mat_nr here, we store a portion of me->mface in Primitive
00476         Primitive prim = {mface, 0};
00477         COLLADAFW::IndexListArray& index_list_array = mp->getUVCoordIndicesArray();
00478 
00479 #ifdef COLLADA_DEBUG
00480         /*
00481         fprintf(stderr, "Primitive %d:\n", i);
00482         for (int j = 0; j < totuvset; j++) {
00483             print_index_list(*index_list_array[j]);
00484         }
00485         */
00486 #endif
00487         
00488         if (type == COLLADAFW::MeshPrimitive::TRIANGLES) {
00489             for (j = 0; j < prim_totface; j++){
00490                 
00491                 set_face_indices(mface, indices, false);
00492                 indices += 3;
00493 
00494 #if 0
00495                 for (k = 0; k < totuvset; k++) {
00496                     if (!index_list_array.empty() && index_list_array[k]) {
00497                         // get mtface by face index and uv set index
00498                         MTFace *mtface = (MTFace*)CustomData_get_layer_n(&me->fdata, CD_MTFACE, k);
00499                         set_face_uv(&mtface[face_index], uvs, k, *index_list_array[k], index, false);
00500                     }
00501                 }
00502 #else
00503                 for (k = 0; k < index_list_array.getCount(); k++) {
00504                     // get mtface by face index and uv set index
00505                     MTFace *mtface = (MTFace*)CustomData_get_layer_n(&me->fdata, CD_MTFACE, k);
00506                     set_face_uv(&mtface[face_index], uvs, *index_list_array[k], index, false);
00507                 }
00508 #endif
00509 
00510                 test_index_face(mface, &me->fdata, face_index, 3);
00511 
00512                 if (has_normals) {
00513                     if (!flat_face(nind, nor, 3))
00514                         mface->flag |= ME_SMOOTH;
00515 
00516                     nind += 3;
00517                 }
00518                 
00519                 index += 3;
00520                 mface++;
00521                 face_index++;
00522                 prim.totface++;
00523             }
00524         }
00525 
00526         // If MeshPrimitive is TRIANGLE_FANS we split it into triangles
00527         // The first trifan vertex will be the first vertex in every triangle
00528         if (type == COLLADAFW::MeshPrimitive::TRIANGLE_FANS) {
00529             unsigned grouped_vertex_count = mp->getGroupedVertexElementsCount();
00530             for (unsigned int group_index = 0; group_index < grouped_vertex_count; group_index++){
00531                 unsigned int first_vertex = indices[0]; // Store first trifan vertex
00532                 unsigned int first_normal = nind[0]; // Store first trifan vertex normal
00533                 unsigned int vertex_count = mp->getGroupedVerticesVertexCount(group_index);
00534 
00535                 for (unsigned int vertex_index = 0; vertex_index < vertex_count - 2; vertex_index++){
00536                     // For each triangle store indeces of its 3 vertices
00537                     unsigned int triangle_vertex_indices[3]={first_vertex, indices[1], indices[2]};
00538                     set_face_indices(mface, triangle_vertex_indices, false);
00539                     test_index_face(mface, &me->fdata, face_index, 3);
00540 
00541                     if (has_normals) {  // vertex normals, same inplementation as for the triangles
00542                         // the same for vertces normals
00543                         unsigned int vertex_normal_indices[3]={first_normal, nind[1], nind[2]};
00544                         if (!flat_face(vertex_normal_indices, nor, 3))
00545                             mface->flag |= ME_SMOOTH;
00546                             nind++;
00547                         }
00548 
00549                         mface++;    // same inplementation as for the triangles
00550                         indices++;
00551                         face_index++;
00552                         prim.totface++;
00553                     }
00554                 
00555                 // Moving cursor  to the next triangle fan.
00556                 if (has_normals)
00557                     nind += 2;
00558 
00559                 indices +=  2;
00560             }
00561         }
00562         else if (type == COLLADAFW::MeshPrimitive::POLYLIST || type == COLLADAFW::MeshPrimitive::POLYGONS) {
00563             COLLADAFW::Polygons *mpvc = (COLLADAFW::Polygons*)mp;
00564             COLLADAFW::Polygons::VertexCountArray& vcounta = mpvc->getGroupedVerticesVertexCountArray();
00565             
00566             for (j = 0; j < prim_totface; j++) {
00567                 
00568                 // face
00569                 int vcount = vcounta[j];
00570                 if (vcount == 3 || vcount == 4) {
00571                     
00572                     set_face_indices(mface, indices, vcount == 4);
00573                     
00574                     // set mtface for each uv set
00575                     // it is assumed that all primitives have equal number of UV sets
00576                     
00577 #if 0
00578                     for (k = 0; k < totuvset; k++) {
00579                         if (!index_list_array.empty() && index_list_array[k]) {
00580                             // get mtface by face index and uv set index
00581                             MTFace *mtface = (MTFace*)CustomData_get_layer_n(&me->fdata, CD_MTFACE, k);
00582                             set_face_uv(&mtface[face_index], uvs, k, *index_list_array[k], index, mface->v4 != 0);
00583                         }
00584                     }
00585 #else
00586                     for (k = 0; k < index_list_array.getCount(); k++) {
00587                         // get mtface by face index and uv set index
00588                         MTFace *mtface = (MTFace*)CustomData_get_layer_n(&me->fdata, CD_MTFACE, k);
00589                         set_face_uv(&mtface[face_index], uvs, *index_list_array[k], index, vcount == 4);
00590                     }
00591 #endif
00592 
00593                     test_index_face(mface, &me->fdata, face_index, vcount);
00594 
00595                     if (has_normals) {
00596                         if (!flat_face(nind, nor, vcount))
00597                             mface->flag |= ME_SMOOTH;
00598 
00599                         nind += vcount;
00600                     }
00601                     
00602                     mface++;
00603                     face_index++;
00604                     prim.totface++;
00605                     
00606                 }
00607                 else {
00608                     std::vector<unsigned int> tri;
00609                     
00610                     triangulate_poly(indices, vcount, me->mvert, tri);
00611                     
00612                     for (k = 0; k < tri.size() / 3; k++) {
00613                         int v = k * 3;
00614                         unsigned int uv_indices[3] = {
00615                             index + tri[v],
00616                             index + tri[v + 1],
00617                             index + tri[v + 2]
00618                         };
00619                         unsigned int tri_indices[3] = {
00620                             indices[tri[v]],
00621                             indices[tri[v + 1]],
00622                             indices[tri[v + 2]]
00623                         };
00624 
00625                         set_face_indices(mface, tri_indices, false);
00626                         
00627 #if 0
00628                         for (unsigned int l = 0; l < totuvset; l++) {
00629                             if (!index_list_array.empty() && index_list_array[l]) {
00630                                 // get mtface by face index and uv set index
00631                                 MTFace *mtface = (MTFace*)CustomData_get_layer_n(&me->fdata, CD_MTFACE, l);
00632                                 set_face_uv(&mtface[face_index], uvs, l, *index_list_array[l], uv_indices);
00633                             }
00634                         }
00635 #else
00636                         for (unsigned int l = 0; l < index_list_array.getCount(); l++) {
00637                             int uvset_index = index_list_array[l]->getSetIndex();
00638 
00639                             // get mtface by face index and uv set index
00640                             MTFace *mtface = (MTFace*)CustomData_get_layer_n(&me->fdata, CD_MTFACE, uvset_index);
00641                             set_face_uv(&mtface[face_index], uvs, *index_list_array[l], uv_indices);
00642                         }
00643 #endif
00644 
00645 
00646                         test_index_face(mface, &me->fdata, face_index, 3);
00647 
00648                         if (has_normals) {
00649                             unsigned int ntri[3] = {nind[tri[v]], nind[tri[v + 1]], nind[tri[v + 2]]};
00650 
00651                             if (!flat_face(ntri, nor, 3))
00652                                 mface->flag |= ME_SMOOTH;
00653                         }
00654                         
00655                         mface++;
00656                         face_index++;
00657                         prim.totface++;
00658                     }
00659 
00660                     if (has_normals)
00661                         nind += vcount;
00662                 }
00663 
00664                 index += vcount;
00665                 indices += vcount;
00666             }
00667         }
00668         
00669         mat_prim_map[mp->getMaterialId()].push_back(prim);
00670     }
00671 
00672     geom_uid_mat_mapping_map[mesh->getUniqueId()] = mat_prim_map;
00673 }
00674 
00675 void MeshImporter::get_vector(float v[3], COLLADAFW::MeshVertexData& arr, int i, int stride)
00676 {
00677     i *= stride;
00678     
00679     switch(arr.getType()) {
00680     case COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT:
00681         {
00682             COLLADAFW::ArrayPrimitiveType<float>* values = arr.getFloatValues();
00683             if (values->empty()) return;
00684 
00685             v[0] = (*values)[i++];
00686             v[1] = (*values)[i++];
00687             v[2] = (*values)[i];
00688 
00689         }
00690         break;
00691     case COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE:
00692         {
00693             COLLADAFW::ArrayPrimitiveType<double>* values = arr.getDoubleValues();
00694             if (values->empty()) return;
00695 
00696             v[0] = (float)(*values)[i++];
00697             v[1] = (float)(*values)[i++];
00698             v[2] = (float)(*values)[i];
00699         }
00700         break;
00701     default:
00702         break;
00703     }
00704 }
00705 
00706 bool MeshImporter::flat_face(unsigned int *nind, COLLADAFW::MeshVertexData& nor, int count)
00707 {
00708     float a[3], b[3];
00709 
00710     get_vector(a, nor, *nind, 3);
00711     normalize_v3(a);
00712 
00713     nind++;
00714 
00715     for (int i = 1; i < count; i++, nind++) {
00716         get_vector(b, nor, *nind, 3);
00717         normalize_v3(b);
00718 
00719         float dp = dot_v3v3(a, b);
00720 
00721         if (dp < 0.99999f || dp > 1.00001f)
00722             return false;
00723     }
00724 
00725     return true;
00726 }
00727 
00728 MeshImporter::MeshImporter(UnitConverter *unitconv, ArmatureImporter *arm, Scene *sce) : unitconverter(unitconv), scene(sce), armature_importer(arm) {}
00729 
00730 Object *MeshImporter::get_object_by_geom_uid(const COLLADAFW::UniqueId& geom_uid)
00731 {
00732     if (uid_object_map.find(geom_uid) != uid_object_map.end())
00733         return uid_object_map[geom_uid];
00734     return NULL;
00735 }
00736 
00737 MTex *MeshImporter::assign_textures_to_uvlayer(COLLADAFW::TextureCoordinateBinding &ctexture,
00738                                  Mesh *me, TexIndexTextureArrayMap& texindex_texarray_map,
00739                                  MTex *color_texture)
00740 {
00741     const COLLADAFW::TextureMapId texture_index = ctexture.getTextureMapId();
00742     size_t setindex = ctexture.getSetIndex();
00743     std::string uvname = ctexture.getSemantic();
00744     
00745     if(setindex==-1) return NULL;
00746     
00747     const CustomData *data = &me->fdata;
00748     int layer_index = CustomData_get_layer_index(data, CD_MTFACE);
00749     CustomDataLayer *cdl = &data->layers[layer_index+setindex];
00750     
00751     /* set uvname to bind_vertex_input semantic */
00752     BLI_strncpy(cdl->name, uvname.c_str(), sizeof(cdl->name));
00753 
00754     if (texindex_texarray_map.find(texture_index) == texindex_texarray_map.end()) {
00755         
00756         fprintf(stderr, "Cannot find texture array by texture index.\n");
00757         return color_texture;
00758     }
00759     
00760     std::vector<MTex*> textures = texindex_texarray_map[texture_index];
00761     
00762     std::vector<MTex*>::iterator it;
00763     
00764     for (it = textures.begin(); it != textures.end(); it++) {
00765         
00766         MTex *texture = *it;
00767         
00768         if (texture) {
00769             BLI_strncpy(texture->uvname, uvname.c_str(), sizeof(texture->uvname));
00770             if (texture->mapto == MAP_COL) color_texture = texture;
00771         }
00772     }
00773     return color_texture;
00774 }
00775 
00776 MTFace *MeshImporter::assign_material_to_geom(COLLADAFW::MaterialBinding cmaterial,
00777                                 std::map<COLLADAFW::UniqueId, Material*>& uid_material_map,
00778                                 Object *ob, const COLLADAFW::UniqueId *geom_uid, 
00779                                 MTex **color_texture, char *layername, MTFace *texture_face,
00780                                 std::map<Material*, TexIndexTextureArrayMap>& material_texture_mapping_map, short mat_index)
00781 {
00782     Mesh *me = (Mesh*)ob->data;
00783     const COLLADAFW::UniqueId& ma_uid = cmaterial.getReferencedMaterial();
00784     
00785     // do we know this material?
00786     if (uid_material_map.find(ma_uid) == uid_material_map.end()) {
00787         
00788         fprintf(stderr, "Cannot find material by UID.\n");
00789         return NULL;
00790     }
00791     
00792     // different nodes can point to same geometry, but still also specify the same materials
00793     // again. Make sure we don't overwrite them on the next occurrences, so keep list of
00794     // what we already have handled.
00795     std::multimap<COLLADAFW::UniqueId, COLLADAFW::UniqueId>::iterator it;
00796     it=materials_mapped_to_geom.find(*geom_uid);
00797     while(it!=materials_mapped_to_geom.end()) {
00798         if(it->second == ma_uid && it->first == *geom_uid) return NULL; // do nothing if already found
00799         it++;
00800     }
00801     // first time we get geom_uid, ma_uid pair. Save for later check.
00802     materials_mapped_to_geom.insert(std::pair<COLLADAFW::UniqueId, COLLADAFW::UniqueId>(*geom_uid, ma_uid));
00803     
00804     Material *ma = uid_material_map[ma_uid];
00805     assign_material(ob, ma, ob->totcol + 1);
00806     
00807     COLLADAFW::TextureCoordinateBindingArray& tex_array = 
00808         cmaterial.getTextureCoordinateBindingArray();
00809     TexIndexTextureArrayMap texindex_texarray_map = material_texture_mapping_map[ma];
00810     unsigned int i;
00811     // loop through <bind_vertex_inputs>
00812     for (i = 0; i < tex_array.getCount(); i++) {
00813         
00814         *color_texture = assign_textures_to_uvlayer(tex_array[i], me, texindex_texarray_map,
00815                                                     *color_texture);
00816     }
00817     
00818     // set texture face
00819     if (*color_texture &&
00820         strlen((*color_texture)->uvname) &&
00821         strcmp(layername, (*color_texture)->uvname) != 0) {
00822         texture_face = (MTFace*)CustomData_get_layer_named(&me->fdata, CD_MTFACE,
00823                                                            (*color_texture)->uvname);
00824         strcpy(layername, (*color_texture)->uvname);
00825     }
00826     
00827     MaterialIdPrimitiveArrayMap& mat_prim_map = geom_uid_mat_mapping_map[*geom_uid];
00828     COLLADAFW::MaterialId mat_id = cmaterial.getMaterialId();
00829     
00830     // assign material indices to mesh faces
00831     if (mat_prim_map.find(mat_id) != mat_prim_map.end()) {
00832         
00833         std::vector<Primitive>& prims = mat_prim_map[mat_id];
00834         
00835         std::vector<Primitive>::iterator it;
00836         
00837         for (it = prims.begin(); it != prims.end(); it++) {
00838             Primitive& prim = *it;
00839             i = 0;
00840             while (i++ < prim.totface) {
00841                 prim.mface->mat_nr = mat_index;
00842                 prim.mface++;
00843                 // bind texture images to faces
00844                 if (texture_face && (*color_texture)) {
00845                     texture_face->mode = TF_TEX;
00846                     texture_face->tpage = (Image*)(*color_texture)->tex->ima;
00847                     texture_face++;
00848                 }
00849             }
00850         }
00851     }
00852     
00853     return texture_face;
00854 }
00855 
00856 
00857 Object *MeshImporter::create_mesh_object(COLLADAFW::Node *node, COLLADAFW::InstanceGeometry *geom,
00858                            bool isController,
00859                            std::map<COLLADAFW::UniqueId, Material*>& uid_material_map,
00860                            std::map<Material*, TexIndexTextureArrayMap>& material_texture_mapping_map)
00861 {
00862     const COLLADAFW::UniqueId *geom_uid = &geom->getInstanciatedObjectId();
00863     
00864     // check if node instanciates controller or geometry
00865     if (isController) {
00866         
00867         geom_uid = armature_importer->get_geometry_uid(*geom_uid);
00868         
00869         if (!geom_uid) {
00870             fprintf(stderr, "Couldn't find a mesh UID by controller's UID.\n");
00871             return NULL;
00872         }
00873     }
00874     else {
00875         
00876         if (uid_mesh_map.find(*geom_uid) == uid_mesh_map.end()) {
00877             // this could happen if a mesh was not created
00878             // (e.g. if it contains unsupported geometry)
00879             fprintf(stderr, "Couldn't find a mesh by UID.\n");
00880             return NULL;
00881         }
00882     }
00883     if (!uid_mesh_map[*geom_uid]) return NULL;
00884     
00885     Object *ob = add_object(scene, OB_MESH);
00886 
00887     // store object pointer for ArmatureImporter
00888     uid_object_map[*geom_uid] = ob;
00889     
00890     // name Object
00891     const std::string& id = node->getName().size() ? node->getName() : node->getOriginalId();
00892     if (id.length())
00893         rename_id(&ob->id, (char*)id.c_str());
00894     
00895     // replace ob->data freeing the old one
00896     Mesh *old_mesh = (Mesh*)ob->data;
00897 
00898     set_mesh(ob, uid_mesh_map[*geom_uid]);
00899     
00900     if (old_mesh->id.us == 0) free_libblock(&G.main->mesh, old_mesh);
00901     
00902     char layername[100];
00903     layername[0] = '\0';
00904     MTFace *texture_face = NULL;
00905     MTex *color_texture = NULL;
00906     
00907     COLLADAFW::MaterialBindingArray& mat_array =
00908         geom->getMaterialBindings();
00909     
00910     // loop through geom's materials
00911     for (unsigned int i = 0; i < mat_array.getCount(); i++) {
00912         
00913         if(mat_array[i].getReferencedMaterial().isValid()) {
00914             texture_face = assign_material_to_geom(mat_array[i], uid_material_map, ob, geom_uid,
00915                                                    &color_texture, layername, texture_face,
00916                                                    material_texture_mapping_map, i);
00917         } else {
00918             fprintf(stderr, "invalid referenced material for %s\n", mat_array[i].getName().c_str());
00919         }
00920     }
00921         
00922     return ob;
00923 }
00924 
00925 // create a mesh storing a pointer in a map so it can be retrieved later by geometry UID
00926 bool MeshImporter::write_geometry(const COLLADAFW::Geometry* geom) 
00927 {
00928     // TODO: import also uvs, normals
00929     // XXX what to do with normal indices?
00930     // XXX num_normals may be != num verts, then what to do?
00931 
00932     // check geometry->getType() first
00933     if (geom->getType() != COLLADAFW::Geometry::GEO_TYPE_MESH) {
00934         // TODO: report warning
00935         fprintf(stderr, "Mesh type %s is not supported\n", bc_geomTypeToStr(geom->getType()));
00936         return true;
00937     }
00938     
00939     COLLADAFW::Mesh *mesh = (COLLADAFW::Mesh*)geom;
00940     
00941     if (!is_nice_mesh(mesh)) {
00942         fprintf(stderr, "Ignoring mesh %s\n", bc_get_dae_name(mesh));
00943         return true;
00944     }
00945     
00946     const std::string& str_geom_id = mesh->getName().size() ? mesh->getName() : mesh->getOriginalId();
00947     Mesh *me = add_mesh((char*)str_geom_id.c_str());
00948 
00949     // store the Mesh pointer to link it later with an Object
00950     this->uid_mesh_map[mesh->getUniqueId()] = me;
00951     
00952     int new_tris = 0;
00953     
00954     read_vertices(mesh, me);
00955 
00956     new_tris = count_new_tris(mesh, me);
00957     
00958     read_faces(mesh, me, new_tris);
00959 
00960     make_edges(me, 0);
00961     
00962     mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL);
00963 
00964     return true;
00965 }