diff options
author | Nathan Letwory <nathan@letworyinteractive.com> | 2010-10-05 04:05:14 +0400 |
---|---|---|
committer | Nathan Letwory <nathan@letworyinteractive.com> | 2010-10-05 04:05:14 +0400 |
commit | 82209cdc86f5f248102df89b3dfeca86149768f7 (patch) | |
tree | 21ce50ed95bc62544d76754c9512ac791e52ca44 /source/blender/collada/MeshImporter.cpp | |
parent | 63b4c93e449902da3bb9a17d4f8b9f8ef7d00ae5 (diff) |
Reorganisation of COLLADA import code. Classes have been split into their own files.
No functional changes.
Where necessary extern "C" {} blocks have been added.
Diffstat (limited to 'source/blender/collada/MeshImporter.cpp')
-rw-r--r-- | source/blender/collada/MeshImporter.cpp | 907 |
1 files changed, 907 insertions, 0 deletions
diff --git a/source/blender/collada/MeshImporter.cpp b/source/blender/collada/MeshImporter.cpp new file mode 100644 index 00000000000..a210eb3b2e0 --- /dev/null +++ b/source/blender/collada/MeshImporter.cpp @@ -0,0 +1,907 @@ +/** + * $Id: DocumentImporter.cpp 32235 2010-10-01 19:46:42Z jesterking $ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Chingiz Dyussenov, Arystanbek Dyussenov, Nathan Letwory. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include <algorithm> + +#include "COLLADAFWMeshPrimitive.h" +#include "COLLADAFWMeshVertexData.h" +#include "COLLADAFWPolygons.h" + +extern "C" { +#include "BKE_blender.h" +#include "BKE_customdata.h" +#include "BKE_displist.h" +#include "BKE_global.h" +#include "BKE_library.h" +#include "BKE_main.h" +#include "BKE_material.h" +#include "BKE_mesh.h" +#include "BKE_object.h" + +#include "BLI_listbase.h" +#include "BLI_math.h" +#include "BLI_string.h" + +#include "MEM_guardedalloc.h" +} + +#include "ArmatureImporter.h" +#include "MeshImporter.h" +#include "collada_utils.h" + +// works for COLLADAFW::Node, COLLADAFW::Geometry +template<class T> +static const char *bc_get_dae_name(T *node) +{ + const std::string& name = node->getName(); + return name.size() ? name.c_str() : node->getOriginalId().c_str(); +} + +static const char *bc_primTypeToStr(COLLADAFW::MeshPrimitive::PrimitiveType type) +{ + switch (type) { + case COLLADAFW::MeshPrimitive::LINES: + return "LINES"; + case COLLADAFW::MeshPrimitive::LINE_STRIPS: + return "LINESTRIPS"; + case COLLADAFW::MeshPrimitive::POLYGONS: + return "POLYGONS"; + case COLLADAFW::MeshPrimitive::POLYLIST: + return "POLYLIST"; + case COLLADAFW::MeshPrimitive::TRIANGLES: + return "TRIANGLES"; + case COLLADAFW::MeshPrimitive::TRIANGLE_FANS: + return "TRIANGLE_FANS"; + case COLLADAFW::MeshPrimitive::TRIANGLE_STRIPS: + return "TRIANGLE_FANS"; + case COLLADAFW::MeshPrimitive::POINTS: + return "POINTS"; + case COLLADAFW::MeshPrimitive::UNDEFINED_PRIMITIVE_TYPE: + return "UNDEFINED_PRIMITIVE_TYPE"; + } + return "UNKNOWN"; +} + +static const char *bc_geomTypeToStr(COLLADAFW::Geometry::GeometryType type) +{ + switch (type) { + case COLLADAFW::Geometry::GEO_TYPE_MESH: + return "MESH"; + case COLLADAFW::Geometry::GEO_TYPE_SPLINE: + return "SPLINE"; + case COLLADAFW::Geometry::GEO_TYPE_CONVEX_MESH: + return "CONVEX_MESH"; + case COLLADAFW::Geometry::GEO_TYPE_UNKNOWN: + default: + return "UNKNOWN"; + } +} + + +UVDataWrapper::UVDataWrapper(COLLADAFW::MeshVertexData& vdata) : mVData(&vdata) +{} + +#ifdef COLLADA_DEBUG +void WVDataWrapper::print() +{ + fprintf(stderr, "UVs:\n"); + switch(mVData->getType()) { + case COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT: + { + COLLADAFW::ArrayPrimitiveType<float>* values = mVData->getFloatValues(); + if (values->getCount()) { + for (int i = 0; i < values->getCount(); i += 2) { + fprintf(stderr, "%.1f, %.1f\n", (*values)[i], (*values)[i+1]); + } + } + } + break; + case COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE: + { + COLLADAFW::ArrayPrimitiveType<double>* values = mVData->getDoubleValues(); + if (values->getCount()) { + for (int i = 0; i < values->getCount(); i += 2) { + fprintf(stderr, "%.1f, %.1f\n", (float)(*values)[i], (float)(*values)[i+1]); + } + } + } + break; + } + fprintf(stderr, "\n"); +} +#endif + +void UVDataWrapper::getUV(int uv_index[2], float *uv) +{ + switch(mVData->getType()) { + case COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT: + { + COLLADAFW::ArrayPrimitiveType<float>* values = mVData->getFloatValues(); + if (values->empty()) return; + uv[0] = (*values)[uv_index[0]]; + uv[1] = (*values)[uv_index[1]]; + + } + break; + case COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE: + { + COLLADAFW::ArrayPrimitiveType<double>* values = mVData->getDoubleValues(); + if (values->empty()) return; + uv[0] = (float)(*values)[uv_index[0]]; + uv[1] = (float)(*values)[uv_index[1]]; + + } + break; + case COLLADAFW::MeshVertexData::DATA_TYPE_UNKNOWN: + default: + fprintf(stderr, "MeshImporter.getUV(): unknown data type\n"); + } +} + +void MeshImporter::set_face_indices(MFace *mface, unsigned int *indices, bool quad) +{ + mface->v1 = indices[0]; + mface->v2 = indices[1]; + mface->v3 = indices[2]; + if (quad) mface->v4 = indices[3]; + else mface->v4 = 0; +#ifdef COLLADA_DEBUG + // fprintf(stderr, "%u, %u, %u \n", indices[0], indices[1], indices[2]); +#endif +} + +// not used anymore, test_index_face from blenkernel is better +#if 0 +// change face indices order so that v4 is not 0 +void MeshImporter::rotate_face_indices(MFace *mface) { + mface->v4 = mface->v1; + mface->v1 = mface->v2; + mface->v2 = mface->v3; + mface->v3 = 0; +} +#endif + +void MeshImporter::set_face_uv(MTFace *mtface, UVDataWrapper &uvs, + COLLADAFW::IndexList& index_list, unsigned int *tris_indices) +{ + int uv_indices[4][2]; + + // per face vertex indices, this means for quad we have 4 indices, not 8 + COLLADAFW::UIntValuesArray& indices = index_list.getIndices(); + + // make indices into FloatOrDoubleArray + for (int i = 0; i < 3; i++) { + int uv_index = indices[tris_indices[i]]; + uv_indices[i][0] = uv_index * 2; + uv_indices[i][1] = uv_index * 2 + 1; + } + + uvs.getUV(uv_indices[0], mtface->uv[0]); + uvs.getUV(uv_indices[1], mtface->uv[1]); + uvs.getUV(uv_indices[2], mtface->uv[2]); +} + +void MeshImporter::set_face_uv(MTFace *mtface, UVDataWrapper &uvs, + COLLADAFW::IndexList& index_list, int index, bool quad) +{ + int uv_indices[4][2]; + + // per face vertex indices, this means for quad we have 4 indices, not 8 + COLLADAFW::UIntValuesArray& indices = index_list.getIndices(); + + // make indices into FloatOrDoubleArray + for (int i = 0; i < (quad ? 4 : 3); i++) { + int uv_index = indices[index + i]; + uv_indices[i][0] = uv_index * 2; + uv_indices[i][1] = uv_index * 2 + 1; + } + + uvs.getUV(uv_indices[0], mtface->uv[0]); + uvs.getUV(uv_indices[1], mtface->uv[1]); + uvs.getUV(uv_indices[2], mtface->uv[2]); + + if (quad) uvs.getUV(uv_indices[3], mtface->uv[3]); + +#ifdef COLLADA_DEBUG + /*if (quad) { + fprintf(stderr, "face uv:\n" + "((%d, %d), (%d, %d), (%d, %d), (%d, %d))\n" + "((%.1f, %.1f), (%.1f, %.1f), (%.1f, %.1f), (%.1f, %.1f))\n", + + uv_indices[0][0], uv_indices[0][1], + uv_indices[1][0], uv_indices[1][1], + uv_indices[2][0], uv_indices[2][1], + uv_indices[3][0], uv_indices[3][1], + + mtface->uv[0][0], mtface->uv[0][1], + mtface->uv[1][0], mtface->uv[1][1], + mtface->uv[2][0], mtface->uv[2][1], + mtface->uv[3][0], mtface->uv[3][1]); + } + else { + fprintf(stderr, "face uv:\n" + "((%d, %d), (%d, %d), (%d, %d))\n" + "((%.1f, %.1f), (%.1f, %.1f), (%.1f, %.1f))\n", + + uv_indices[0][0], uv_indices[0][1], + uv_indices[1][0], uv_indices[1][1], + uv_indices[2][0], uv_indices[2][1], + + mtface->uv[0][0], mtface->uv[0][1], + mtface->uv[1][0], mtface->uv[1][1], + mtface->uv[2][0], mtface->uv[2][1]); + }*/ +#endif +} + +#ifdef COLLADA_DEBUG +void MeshImporter::print_index_list(COLLADAFW::IndexList& index_list) +{ + fprintf(stderr, "Index list for \"%s\":\n", index_list.getName().c_str()); + for (int i = 0; i < index_list.getIndicesCount(); i += 2) { + fprintf(stderr, "%u, %u\n", index_list.getIndex(i), index_list.getIndex(i + 1)); + } + fprintf(stderr, "\n"); +} +#endif + +bool MeshImporter::is_nice_mesh(COLLADAFW::Mesh *mesh) +{ + COLLADAFW::MeshPrimitiveArray& prim_arr = mesh->getMeshPrimitives(); + + const char *name = bc_get_dae_name(mesh); + + for (unsigned i = 0; i < prim_arr.getCount(); i++) { + + COLLADAFW::MeshPrimitive *mp = prim_arr[i]; + COLLADAFW::MeshPrimitive::PrimitiveType type = mp->getPrimitiveType(); + + const char *type_str = bc_primTypeToStr(type); + + // OpenCollada passes POLYGONS type for <polylist> + if (type == COLLADAFW::MeshPrimitive::POLYLIST || type == COLLADAFW::MeshPrimitive::POLYGONS) { + + COLLADAFW::Polygons *mpvc = (COLLADAFW::Polygons*)mp; + COLLADAFW::Polygons::VertexCountArray& vca = mpvc->getGroupedVerticesVertexCountArray(); + + for(unsigned int j = 0; j < vca.getCount(); j++){ + int count = vca[j]; + if (count < 3) { + fprintf(stderr, "Primitive %s in %s has at least one face with vertex count < 3\n", + type_str, name); + return false; + } + } + + } + else if(type != COLLADAFW::MeshPrimitive::TRIANGLES) { + fprintf(stderr, "Primitive type %s is not supported.\n", type_str); + return false; + } + } + + if (mesh->getPositions().empty()) { + fprintf(stderr, "Mesh %s has no vertices.\n", name); + return false; + } + + return true; +} + +void MeshImporter::read_vertices(COLLADAFW::Mesh *mesh, Mesh *me) +{ + // vertices + me->totvert = mesh->getPositions().getFloatValues()->getCount() / 3; + me->mvert = (MVert*)CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, me->totvert); + + COLLADAFW::MeshVertexData& pos = mesh->getPositions(); + MVert *mvert; + int i; + + for (i = 0, mvert = me->mvert; i < me->totvert; i++, mvert++) + get_vector(mvert->co, pos, i); +} + +int MeshImporter::triangulate_poly(unsigned int *indices, int totvert, MVert *verts, std::vector<unsigned int>& tri) +{ + ListBase dispbase; + DispList *dl; + float *vert; + int i = 0; + + dispbase.first = dispbase.last = NULL; + + dl = (DispList*)MEM_callocN(sizeof(DispList), "poly disp"); + dl->nr = totvert; + dl->type = DL_POLY; + dl->parts = 1; + dl->verts = vert = (float*)MEM_callocN(totvert * 3 * sizeof(float), "poly verts"); + dl->index = (int*)MEM_callocN(sizeof(int) * 3 * totvert, "dl index"); + + BLI_addtail(&dispbase, dl); + + for (i = 0; i < totvert; i++) { + copy_v3_v3(vert, verts[indices[i]].co); + vert += 3; + } + + filldisplist(&dispbase, &dispbase, 0); + + int tottri = 0; + dl= (DispList*)dispbase.first; + + if (dl->type == DL_INDEX3) { + tottri = dl->parts; + + int *index = dl->index; + for (i= 0; i < tottri; i++) { + int t[3]= {*index, *(index + 1), *(index + 2)}; + + std::sort(t, t + 3); + + tri.push_back(t[0]); + tri.push_back(t[1]); + tri.push_back(t[2]); + + index += 3; + } + } + + freedisplist(&dispbase); + + return tottri; +} + +int MeshImporter::count_new_tris(COLLADAFW::Mesh *mesh, Mesh *me) +{ + COLLADAFW::MeshPrimitiveArray& prim_arr = mesh->getMeshPrimitives(); + unsigned int i; + int tottri = 0; + + for (i = 0; i < prim_arr.getCount(); i++) { + + COLLADAFW::MeshPrimitive *mp = prim_arr[i]; + int type = mp->getPrimitiveType(); + size_t prim_totface = mp->getFaceCount(); + unsigned int *indices = mp->getPositionIndices().getData(); + + if (type == COLLADAFW::MeshPrimitive::POLYLIST || + type == COLLADAFW::MeshPrimitive::POLYGONS) { + + COLLADAFW::Polygons *mpvc = (COLLADAFW::Polygons*)mp; + COLLADAFW::Polygons::VertexCountArray& vcounta = mpvc->getGroupedVerticesVertexCountArray(); + + for (unsigned int j = 0; j < prim_totface; j++) { + int vcount = vcounta[j]; + + if (vcount > 4) { + std::vector<unsigned int> tri; + + // tottri += triangulate_poly(indices, vcount, me->mvert, tri) - 1; // XXX why - 1?! + tottri += triangulate_poly(indices, vcount, me->mvert, tri); + } + + indices += vcount; + } + } + } + return tottri; +} + +// TODO: import uv set names +void MeshImporter::read_faces(COLLADAFW::Mesh *mesh, Mesh *me, int new_tris) +{ + unsigned int i; + + // allocate faces + me->totface = mesh->getFacesCount() + new_tris; + me->mface = (MFace*)CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, NULL, me->totface); + + // allocate UV layers + unsigned int totuvset = mesh->getUVCoords().getInputInfosArray().getCount(); + + for (i = 0; i < totuvset; i++) { + if (mesh->getUVCoords().getLength(i) == 0) { + totuvset = 0; + break; + } + } + + for (i = 0; i < totuvset; i++) { + COLLADAFW::MeshVertexData::InputInfos *info = mesh->getUVCoords().getInputInfosArray()[i]; + CustomData_add_layer_named(&me->fdata, CD_MTFACE, CD_CALLOC, NULL, me->totface, info->mName.c_str()); + //this->set_layername_map[i] = CustomData_get_layer_name(&me->fdata, CD_MTFACE, i); + } + + // activate the first uv layer + if (totuvset) me->mtface = (MTFace*)CustomData_get_layer_n(&me->fdata, CD_MTFACE, 0); + + UVDataWrapper uvs(mesh->getUVCoords()); + +#ifdef COLLADA_DEBUG + // uvs.print(); +#endif + + MFace *mface = me->mface; + + MaterialIdPrimitiveArrayMap mat_prim_map; + + int face_index = 0; + + COLLADAFW::MeshPrimitiveArray& prim_arr = mesh->getMeshPrimitives(); + + bool has_normals = mesh->hasNormals(); + COLLADAFW::MeshVertexData& nor = mesh->getNormals(); + + for (i = 0; i < prim_arr.getCount(); i++) { + + COLLADAFW::MeshPrimitive *mp = prim_arr[i]; + + // faces + size_t prim_totface = mp->getFaceCount(); + unsigned int *indices = mp->getPositionIndices().getData(); + unsigned int *nind = mp->getNormalIndices().getData(); + unsigned int j, k; + int type = mp->getPrimitiveType(); + int index = 0; + + // since we cannot set mface->mat_nr here, we store a portion of me->mface in Primitive + Primitive prim = {mface, 0}; + COLLADAFW::IndexListArray& index_list_array = mp->getUVCoordIndicesArray(); + +#ifdef COLLADA_DEBUG + /* + fprintf(stderr, "Primitive %d:\n", i); + for (int j = 0; j < totuvset; j++) { + print_index_list(*index_list_array[j]); + } + */ +#endif + + if (type == COLLADAFW::MeshPrimitive::TRIANGLES) { + for (j = 0; j < prim_totface; j++){ + + set_face_indices(mface, indices, false); + indices += 3; + +#if 0 + for (k = 0; k < totuvset; k++) { + if (!index_list_array.empty() && index_list_array[k]) { + // get mtface by face index and uv set index + MTFace *mtface = (MTFace*)CustomData_get_layer_n(&me->fdata, CD_MTFACE, k); + set_face_uv(&mtface[face_index], uvs, k, *index_list_array[k], index, false); + } + } +#else + for (k = 0; k < index_list_array.getCount(); k++) { + int uvset_index = index_list_array[k]->getSetIndex(); + + // get mtface by face index and uv set index + MTFace *mtface = (MTFace*)CustomData_get_layer_n(&me->fdata, CD_MTFACE, uvset_index); + set_face_uv(&mtface[face_index], uvs, *index_list_array[k], index, false); + } +#endif + + test_index_face(mface, &me->fdata, face_index, 3); + + if (has_normals) { + if (!flat_face(nind, nor, 3)) + mface->flag |= ME_SMOOTH; + + nind += 3; + } + + index += 3; + mface++; + face_index++; + prim.totface++; + } + } + else if (type == COLLADAFW::MeshPrimitive::POLYLIST || type == COLLADAFW::MeshPrimitive::POLYGONS) { + COLLADAFW::Polygons *mpvc = (COLLADAFW::Polygons*)mp; + COLLADAFW::Polygons::VertexCountArray& vcounta = mpvc->getGroupedVerticesVertexCountArray(); + + for (j = 0; j < prim_totface; j++) { + + // face + int vcount = vcounta[j]; + if (vcount == 3 || vcount == 4) { + + set_face_indices(mface, indices, vcount == 4); + + // set mtface for each uv set + // it is assumed that all primitives have equal number of UV sets + +#if 0 + for (k = 0; k < totuvset; k++) { + if (!index_list_array.empty() && index_list_array[k]) { + // get mtface by face index and uv set index + MTFace *mtface = (MTFace*)CustomData_get_layer_n(&me->fdata, CD_MTFACE, k); + set_face_uv(&mtface[face_index], uvs, k, *index_list_array[k], index, mface->v4 != 0); + } + } +#else + for (k = 0; k < index_list_array.getCount(); k++) { + int uvset_index = index_list_array[k]->getSetIndex(); + + // get mtface by face index and uv set index + MTFace *mtface = (MTFace*)CustomData_get_layer_n(&me->fdata, CD_MTFACE, uvset_index); + set_face_uv(&mtface[face_index], uvs, *index_list_array[k], index, mface->v4 != 0); + } +#endif + + test_index_face(mface, &me->fdata, face_index, vcount); + + if (has_normals) { + if (!flat_face(nind, nor, vcount)) + mface->flag |= ME_SMOOTH; + + nind += vcount; + } + + mface++; + face_index++; + prim.totface++; + + } + else { + std::vector<unsigned int> tri; + + triangulate_poly(indices, vcount, me->mvert, tri); + + for (k = 0; k < tri.size() / 3; k++) { + int v = k * 3; + unsigned int uv_indices[3] = { + index + tri[v], + index + tri[v + 1], + index + tri[v + 2] + }; + unsigned int tri_indices[3] = { + indices[tri[v]], + indices[tri[v + 1]], + indices[tri[v + 2]] + }; + + set_face_indices(mface, tri_indices, false); + +#if 0 + for (unsigned int l = 0; l < totuvset; l++) { + if (!index_list_array.empty() && index_list_array[l]) { + // get mtface by face index and uv set index + MTFace *mtface = (MTFace*)CustomData_get_layer_n(&me->fdata, CD_MTFACE, l); + set_face_uv(&mtface[face_index], uvs, l, *index_list_array[l], uv_indices); + } + } +#else + for (unsigned int l = 0; l < index_list_array.getCount(); l++) { + int uvset_index = index_list_array[l]->getSetIndex(); + + // get mtface by face index and uv set index + MTFace *mtface = (MTFace*)CustomData_get_layer_n(&me->fdata, CD_MTFACE, uvset_index); + set_face_uv(&mtface[face_index], uvs, *index_list_array[l], uv_indices); + } +#endif + + + test_index_face(mface, &me->fdata, face_index, 3); + + if (has_normals) { + unsigned int ntri[3] = {nind[tri[v]], nind[tri[v + 1]], nind[tri[v + 2]]}; + + if (!flat_face(ntri, nor, 3)) + mface->flag |= ME_SMOOTH; + } + + mface++; + face_index++; + prim.totface++; + } + + if (has_normals) + nind += vcount; + } + + index += vcount; + indices += vcount; + } + } + + mat_prim_map[mp->getMaterialId()].push_back(prim); + } + + geom_uid_mat_mapping_map[mesh->getUniqueId()] = mat_prim_map; +} + +void MeshImporter::get_vector(float v[3], COLLADAFW::MeshVertexData& arr, int i) +{ + i *= 3; + + switch(arr.getType()) { + case COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT: + { + COLLADAFW::ArrayPrimitiveType<float>* values = arr.getFloatValues(); + if (values->empty()) return; + + v[0] = (*values)[i++]; + v[1] = (*values)[i++]; + v[2] = (*values)[i]; + } + break; + case COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE: + { + COLLADAFW::ArrayPrimitiveType<double>* values = arr.getDoubleValues(); + if (values->empty()) return; + + v[0] = (float)(*values)[i++]; + v[1] = (float)(*values)[i++]; + v[2] = (float)(*values)[i]; + } + break; + default: + break; + } +} + +bool MeshImporter::flat_face(unsigned int *nind, COLLADAFW::MeshVertexData& nor, int count) +{ + float a[3], b[3]; + + get_vector(a, nor, *nind); + normalize_v3(a); + + nind++; + + for (int i = 1; i < count; i++, nind++) { + get_vector(b, nor, *nind); + normalize_v3(b); + + float dp = dot_v3v3(a, b); + + if (dp < 0.99999f || dp > 1.00001f) + return false; + } + + return true; +} + +MeshImporter::MeshImporter(ArmatureImporter *arm, Scene *sce) : scene(sce), armature_importer(arm) {} + +Object *MeshImporter::get_object_by_geom_uid(const COLLADAFW::UniqueId& geom_uid) +{ + if (uid_object_map.find(geom_uid) != uid_object_map.end()) + return uid_object_map[geom_uid]; + return NULL; +} + +MTex *MeshImporter::assign_textures_to_uvlayer(COLLADAFW::TextureCoordinateBinding &ctexture, + Mesh *me, TexIndexTextureArrayMap& texindex_texarray_map, + MTex *color_texture) +{ + const COLLADAFW::TextureMapId texture_index = ctexture.getTextureMapId(); + const size_t setindex = ctexture.getSetIndex(); + std::string uvname = ctexture.getName(); + + const CustomData *data = &me->fdata; + int layer_index = CustomData_get_layer_index(data, CD_MTFACE); + CustomDataLayer *cdl = &data->layers[layer_index+setindex]; + + /* set uvname to bind_vertex_input semantic */ + BLI_strncpy(cdl->name, uvname.c_str(), sizeof(cdl->name)); + + if (texindex_texarray_map.find(texture_index) == texindex_texarray_map.end()) { + + fprintf(stderr, "Cannot find texture array by texture index.\n"); + return color_texture; + } + + std::vector<MTex*> textures = texindex_texarray_map[texture_index]; + + std::vector<MTex*>::iterator it; + + for (it = textures.begin(); it != textures.end(); it++) { + + MTex *texture = *it; + + if (texture) { + BLI_strncpy(texture->uvname, uvname.c_str(), sizeof(texture->uvname)); + if (texture->mapto == MAP_COL) color_texture = texture; + } + } + return color_texture; +} + +MTFace *MeshImporter::assign_material_to_geom(COLLADAFW::MaterialBinding cmaterial, + std::map<COLLADAFW::UniqueId, Material*>& uid_material_map, + Object *ob, const COLLADAFW::UniqueId *geom_uid, + MTex **color_texture, char *layername, MTFace *texture_face, + std::map<Material*, TexIndexTextureArrayMap>& material_texture_mapping_map, int mat_index) +{ + Mesh *me = (Mesh*)ob->data; + const COLLADAFW::UniqueId& ma_uid = cmaterial.getReferencedMaterial(); + + // do we know this material? + if (uid_material_map.find(ma_uid) == uid_material_map.end()) { + + fprintf(stderr, "Cannot find material by UID.\n"); + return NULL; + } + + Material *ma = uid_material_map[ma_uid]; + assign_material(ob, ma, ob->totcol + 1); + + COLLADAFW::TextureCoordinateBindingArray& tex_array = + cmaterial.getTextureCoordinateBindingArray(); + TexIndexTextureArrayMap texindex_texarray_map = material_texture_mapping_map[ma]; + unsigned int i; + // loop through <bind_vertex_inputs> + for (i = 0; i < tex_array.getCount(); i++) { + + *color_texture = assign_textures_to_uvlayer(tex_array[i], me, texindex_texarray_map, + *color_texture); + } + + // set texture face + if (*color_texture && + strlen((*color_texture)->uvname) && + strcmp(layername, (*color_texture)->uvname) != 0) { + + texture_face = (MTFace*)CustomData_get_layer_named(&me->fdata, CD_MTFACE, + (*color_texture)->uvname); + strcpy(layername, (*color_texture)->uvname); + } + + MaterialIdPrimitiveArrayMap& mat_prim_map = geom_uid_mat_mapping_map[*geom_uid]; + COLLADAFW::MaterialId mat_id = cmaterial.getMaterialId(); + + // assign material indices to mesh faces + if (mat_prim_map.find(mat_id) != mat_prim_map.end()) { + + std::vector<Primitive>& prims = mat_prim_map[mat_id]; + + std::vector<Primitive>::iterator it; + + for (it = prims.begin(); it != prims.end(); it++) { + Primitive& prim = *it; + i = 0; + while (i++ < prim.totface) { + prim.mface->mat_nr = mat_index; + prim.mface++; + // bind texture images to faces + if (texture_face && (*color_texture)) { + texture_face->mode = TF_TEX; + texture_face->tpage = (Image*)(*color_texture)->tex->ima; + texture_face++; + } + } + } + } + + return texture_face; +} + + +Object *MeshImporter::create_mesh_object(COLLADAFW::Node *node, COLLADAFW::InstanceGeometry *geom, + bool isController, + std::map<COLLADAFW::UniqueId, Material*>& uid_material_map, + std::map<Material*, TexIndexTextureArrayMap>& material_texture_mapping_map) +{ + const COLLADAFW::UniqueId *geom_uid = &geom->getInstanciatedObjectId(); + + // check if node instanciates controller or geometry + if (isController) { + + geom_uid = armature_importer->get_geometry_uid(*geom_uid); + + if (!geom_uid) { + fprintf(stderr, "Couldn't find a mesh UID by controller's UID.\n"); + return NULL; + } + } + else { + + if (uid_mesh_map.find(*geom_uid) == uid_mesh_map.end()) { + // this could happen if a mesh was not created + // (e.g. if it contains unsupported geometry) + fprintf(stderr, "Couldn't find a mesh by UID.\n"); + return NULL; + } + } + if (!uid_mesh_map[*geom_uid]) return NULL; + + Object *ob = add_object(scene, OB_MESH); + + // store object pointer for ArmatureImporter + uid_object_map[*geom_uid] = ob; + + // name Object + const std::string& id = node->getOriginalId(); + if (id.length()) + rename_id(&ob->id, (char*)id.c_str()); + + // replace ob->data freeing the old one + Mesh *old_mesh = (Mesh*)ob->data; + + set_mesh(ob, uid_mesh_map[*geom_uid]); + + if (old_mesh->id.us == 0) free_libblock(&G.main->mesh, old_mesh); + + char layername[100]; + MTFace *texture_face = NULL; + MTex *color_texture = NULL; + + COLLADAFW::MaterialBindingArray& mat_array = + geom->getMaterialBindings(); + + // loop through geom's materials + for (unsigned int i = 0; i < mat_array.getCount(); i++) { + + texture_face = assign_material_to_geom(mat_array[i], uid_material_map, ob, geom_uid, + &color_texture, layername, texture_face, + material_texture_mapping_map, i); + } + + return ob; +} + +// create a mesh storing a pointer in a map so it can be retrieved later by geometry UID +bool MeshImporter::write_geometry(const COLLADAFW::Geometry* geom) +{ + // TODO: import also uvs, normals + // XXX what to do with normal indices? + // XXX num_normals may be != num verts, then what to do? + + // check geometry->getType() first + if (geom->getType() != COLLADAFW::Geometry::GEO_TYPE_MESH) { + // TODO: report warning + fprintf(stderr, "Mesh type %s is not supported\n", bc_geomTypeToStr(geom->getType())); + return true; + } + + COLLADAFW::Mesh *mesh = (COLLADAFW::Mesh*)geom; + + if (!is_nice_mesh(mesh)) { + fprintf(stderr, "Ignoring mesh %s\n", bc_get_dae_name(mesh)); + return true; + } + + const std::string& str_geom_id = mesh->getOriginalId(); + Mesh *me = add_mesh((char*)str_geom_id.c_str()); + + // store the Mesh pointer to link it later with an Object + this->uid_mesh_map[mesh->getUniqueId()] = me; + + int new_tris = 0; + + read_vertices(mesh, me); + + new_tris = count_new_tris(mesh, me); + + read_faces(mesh, me, new_tris); + + make_edges(me, 0); + + mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL); + + return true; +} |