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