|
Blender
V2.59
|
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 }