From 8bdac4d0bc21143bafbdbb9b45ab521dfedfa369 Mon Sep 17 00:00:00 2001 From: gaiaclary Date: Thu, 1 May 2014 14:52:10 +0200 Subject: fix T39967: Added support for Import/export of vertex color layers --- source/blender/collada/GeometryExporter.cpp | 88 ++++++++++++++------- source/blender/collada/GeometryExporter.h | 3 +- source/blender/collada/MeshImporter.cpp | 116 ++++++++++++++++++++++++---- source/blender/collada/MeshImporter.h | 14 ++++ 4 files changed, 180 insertions(+), 41 deletions(-) (limited to 'source') diff --git a/source/blender/collada/GeometryExporter.cpp b/source/blender/collada/GeometryExporter.cpp index 3d5d79f55ea..d54fc713a8c 100644 --- a/source/blender/collada/GeometryExporter.cpp +++ b/source/blender/collada/GeometryExporter.cpp @@ -289,6 +289,12 @@ void GeometryExporter::createLooseEdgeList(Object *ob, } +std::string GeometryExporter::makeVertexColorSourceId(std::string& geom_id, char *layer_name) +{ + std::string result = getIdBySemantics(geom_id, COLLADASW::InputSemantic::COLOR) + "-" + layer_name; + return result; +} + // powerful because it handles both cases when there is material and when there's not void GeometryExporter::createPolylist(short material_index, bool has_uvs, @@ -365,9 +371,20 @@ void GeometryExporter::createPolylist(short material_index, } } - if (has_color) { - COLLADASW::Input input4(COLLADASW::InputSemantic::COLOR, getUrlBySemantics(geom_id, COLLADASW::InputSemantic::COLOR), has_uvs ? 3 : 2); - til.push_back(input4); + int totlayer_mcol = CustomData_number_of_layers(&me->ldata, CD_MLOOPCOL); + if (totlayer_mcol > 0) { + int map_index = 0; + + for (int a = 0; a < totlayer_mcol; a++) { + char *layer_name = bc_CustomData_get_layer_name(&me->ldata, CD_MLOOPCOL, a); + COLLADASW::Input input4(COLLADASW::InputSemantic::COLOR, + makeUrl(makeVertexColorSourceId(geom_id, layer_name)), + (has_uvs) ? 3 : 2, // all color layers have same index order + map_index // set number equals color map index + ); + til.push_back(input4); + map_index++; + } } // sets @@ -420,6 +437,7 @@ void GeometryExporter::createVertsSource(std::string geom_id, Mesh *me) ARRAY_ID_SUFFIX); source.setAccessorCount(totverts); source.setAccessorStride(3); + COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); param.push_back("X"); param.push_back("Y"); @@ -437,40 +455,56 @@ void GeometryExporter::createVertsSource(std::string geom_id, Mesh *me) } + void GeometryExporter::createVertexColorSource(std::string geom_id, Mesh *me) { - MLoopCol *mloopcol = (MLoopCol *)CustomData_get_layer(&me->ldata, CD_MLOOPCOL); - if (mloopcol == NULL) + /* Find number of vertex color layers */ + int totlayer_mcol = CustomData_number_of_layers(&me->ldata, CD_MLOOPCOL); + if (totlayer_mcol == 0) return; + int active_vcolor_index = CustomData_get_active_layer_index(&me->ldata, CD_MLOOPCOL); - COLLADASW::FloatSourceF source(mSW); - source.setId(getIdBySemantics(geom_id, COLLADASW::InputSemantic::COLOR)); - source.setArrayId(getIdBySemantics(geom_id, COLLADASW::InputSemantic::COLOR) + ARRAY_ID_SUFFIX); - source.setAccessorCount(me->totloop); - source.setAccessorStride(3); + int map_index = 0; + for (int a = 0; a < totlayer_mcol; a++) { - COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); - param.push_back("R"); - param.push_back("G"); - param.push_back("B"); + map_index++; + MLoopCol *mloopcol = (MLoopCol *)CustomData_get_layer_n(&me->ldata, CD_MLOOPCOL, a); - source.prepareToAppendValues(); + COLLADASW::FloatSourceF source(mSW); - MPoly *mpoly; - int i; - for (i = 0, mpoly = me->mpoly; i < me->totpoly; i++, mpoly++) { - MLoopCol *mlc = mloopcol + mpoly->loopstart; - for (int j = 0; j < mpoly->totloop; j++, mlc++) { - source.appendValues( - mlc->r / 255.0f, - mlc->g / 255.0f, - mlc->b / 255.0f - ); + char *layer_name = bc_CustomData_get_layer_name(&me->ldata, CD_MLOOPCOL, a); + std::string layer_id = makeVertexColorSourceId(geom_id, layer_name); + source.setId(layer_id); + + source.setNodeName(layer_name); + + source.setArrayId(layer_id + ARRAY_ID_SUFFIX); + source.setAccessorCount(me->totloop); + source.setAccessorStride(3); + + COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); + param.push_back("R"); + param.push_back("G"); + param.push_back("B"); + + source.prepareToAppendValues(); + + MPoly *mpoly; + int i; + for (i = 0, mpoly = me->mpoly; i < me->totpoly; i++, mpoly++) { + MLoopCol *mlc = mloopcol + mpoly->loopstart; + for (int j = 0; j < mpoly->totloop; j++, mlc++) { + source.appendValues( + mlc->r / 255.0f, + mlc->g / 255.0f, + mlc->b / 255.0f + ); + } } - } - source.finish(); + source.finish(); + } } diff --git a/source/blender/collada/GeometryExporter.h b/source/blender/collada/GeometryExporter.h index 5b67f80e98d..4d54e79d796 100644 --- a/source/blender/collada/GeometryExporter.h +++ b/source/blender/collada/GeometryExporter.h @@ -100,7 +100,8 @@ public: void create_normals(std::vector &nor, std::vector &ind, Mesh *me); std::string getIdBySemantics(std::string geom_id, COLLADASW::InputSemantic::Semantics type, std::string other_suffix = ""); - + std::string makeVertexColorSourceId(std::string& geom_id, char *layer_name); + COLLADASW::URI getUrlBySemantics(std::string geom_id, COLLADASW::InputSemantic::Semantics type, std::string other_suffix = ""); COLLADASW::URI makeUrl(std::string id); diff --git a/source/blender/collada/MeshImporter.cpp b/source/blender/collada/MeshImporter.cpp index d631a43676f..8840e1174ea 100644 --- a/source/blender/collada/MeshImporter.cpp +++ b/source/blender/collada/MeshImporter.cpp @@ -173,6 +173,42 @@ void UVDataWrapper::getUV(int uv_index, float *uv) } } +VCOLDataWrapper::VCOLDataWrapper(COLLADAFW::MeshVertexData& vdata) : mVData(&vdata){ +} + +void VCOLDataWrapper::get_vcol(int v_index, MLoopCol *mloopcol) +{ + int stride = mVData->getStride(0); + if(stride == 0) stride =3; + + switch (mVData->getType()) { + case COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT: + { + COLLADAFW::ArrayPrimitiveType *values = mVData->getFloatValues(); + if (values->empty()) return; + + mloopcol->r = FTOCHAR((*values)[v_index * stride]); + mloopcol->g = FTOCHAR((*values)[v_index * stride + 1]); + mloopcol->b = FTOCHAR((*values)[v_index * stride + 2]); + } + break; + + case COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE: + { + COLLADAFW::ArrayPrimitiveType *values = mVData->getDoubleValues(); + if (values->empty()) return; + + mloopcol->r = FTOCHAR((*values)[v_index * stride]); + mloopcol->g = FTOCHAR((*values)[v_index * stride + 1]); + mloopcol->b = FTOCHAR((*values)[v_index * stride + 2]); + } + break; + default: + fprintf(stderr, "VCOLDataWrapper.getvcol(): unknown data type\n"); + } + +} + MeshImporter::MeshImporter(UnitConverter *unitconv, ArmatureImporter *arm, Scene *sce) : unitconverter(unitconv), scene(sce), armature_importer(arm) { } @@ -187,6 +223,17 @@ void MeshImporter::set_poly_indices(MPoly *mpoly, MLoop *mloop, int loop_index, } } +void MeshImporter::set_vcol(MLoopCol *mlc, VCOLDataWrapper &vob, int loop_index, COLLADAFW::IndexList &index_list, int count) +{ + COLLADAFW::UIntValuesArray& indices =index_list.getIndices(); + int index; + for(index = 0; index < count; index++,mlc++) + { + int v_index = indices[index+loop_index]; + vob.get_vcol(v_index,mlc); + } +} + void MeshImporter::set_face_uv(MLoopUV *mloopuv, UVDataWrapper &uvs, int start_index, COLLADAFW::IndexList& index_list, int count) { @@ -328,6 +375,17 @@ bool MeshImporter::primitive_has_faces(COLLADAFW::MeshPrimitive *mp) { return has_faces; } + +static std::string extract_vcolname(const COLLADAFW::String &collada_id) { + std::string colname = collada_id; + int spos = colname.find("-mesh-colors-"); + if (spos != std::string::npos) { + colname = colname.substr(spos+13); + } + return colname; +} + + // ================================================================= // Return the number of faces by summing up // the facecounts of the parts. @@ -337,8 +395,9 @@ bool MeshImporter::primitive_has_faces(COLLADAFW::MeshPrimitive *mp) { void MeshImporter::allocate_poly_data(COLLADAFW::Mesh *collada_mesh, Mesh *me) { COLLADAFW::MeshPrimitiveArray& prim_arr = collada_mesh->getMeshPrimitives(); - int total_poly_count = 0; - int total_loop_count = 0; + int total_poly_count = 0; + int total_loop_count = 0; + int total_color_count = 0; // collect edge_count and face_count from all parts for (int i = 0; i < prim_arr.getCount(); i++) { @@ -360,6 +419,7 @@ void MeshImporter::allocate_poly_data(COLLADAFW::Mesh *collada_mesh, Mesh *me) total_poly_count += prim_poly_count; total_loop_count += prim_loop_count; + break; } default: @@ -394,6 +454,17 @@ void MeshImporter::allocate_poly_data(COLLADAFW::Mesh *collada_mesh, Mesh *me) me->mtpoly = (MTexPoly *)CustomData_get_layer_n(&me->pdata, CD_MTEXPOLY, 0); me->mloopuv = (MLoopUV *) CustomData_get_layer_n(&me->ldata, CD_MLOOPUV, 0); } + + int totcolset = collada_mesh->getColors().getInputInfosArray().getCount(); + if (totcolset > 0) { + for (int i = 0; i < totcolset; i++) { + COLLADAFW::MeshVertexData::InputInfos *info = collada_mesh->getColors().getInputInfosArray()[i]; + COLLADAFW::String colname = extract_vcolname(info->mName); + CustomData_add_layer_named(&me->ldata,CD_MLOOPCOL,CD_DEFAULT,NULL,me->totloop, colname.c_str()); + } + me->mloopcol = (MLoopCol *) CustomData_get_layer_n(&me->ldata, CD_MLOOPCOL, 0); + } + } } @@ -538,6 +609,7 @@ void MeshImporter::read_polys(COLLADAFW::Mesh *collada_mesh, Mesh *me) allocate_poly_data(collada_mesh, me); UVDataWrapper uvs(collada_mesh->getUVCoords()); + VCOLDataWrapper vcol(collada_mesh->getColors()); MPoly *mpoly = me->mpoly; MLoop *mloop = me->mloop; @@ -553,9 +625,9 @@ void MeshImporter::read_polys(COLLADAFW::Mesh *collada_mesh, Mesh *me) COLLADAFW::MeshPrimitive *mp = prim_arr[i]; // faces - size_t prim_totpoly = mp->getFaceCount(); - unsigned int *position_indices = mp->getPositionIndices().getData(); - unsigned int *normal_indices = mp->getNormalIndices().getData(); + size_t prim_totpoly = mp->getFaceCount(); + unsigned int *position_indices = mp->getPositionIndices().getData(); + unsigned int *normal_indices = mp->getNormalIndices().getData(); bool mp_has_normals = primitive_has_useable_normals(mp); bool mp_has_faces = primitive_has_faces(mp); @@ -564,7 +636,6 @@ void MeshImporter::read_polys(COLLADAFW::Mesh *collada_mesh, Mesh *me) // since we cannot set mpoly->mat_nr here, we store a portion of me->mpoly in Primitive Primitive prim = {mpoly, 0}; - COLLADAFW::IndexListArray& index_list_array = mp->getUVCoordIndicesArray(); // If MeshPrimitive is TRIANGLE_FANS we split it into triangles // The first trifan vertex will be the first vertex in every triangle @@ -611,6 +682,9 @@ void MeshImporter::read_polys(COLLADAFW::Mesh *collada_mesh, Mesh *me) COLLADAFW::Polygons *mpvc = (COLLADAFW::Polygons *)mp; unsigned int start_index = 0; + COLLADAFW::IndexListArray& index_list_array_uvcoord = mp->getUVCoordIndicesArray(); + COLLADAFW::IndexListArray& index_list_array_vcolor = mp->getColorIndicesArray(); + for (unsigned int j = 0; j < prim_totpoly; j++) { // Vertices in polygon: @@ -618,15 +692,15 @@ void MeshImporter::read_polys(COLLADAFW::Mesh *collada_mesh, Mesh *me) set_poly_indices(mpoly, mloop, loop_index, position_indices, vcount); - for (unsigned int uvset_index = 0; uvset_index < index_list_array.getCount(); uvset_index++) { + for (unsigned int uvset_index = 0; uvset_index < index_list_array_uvcoord.getCount(); uvset_index++) { // get mtface by face index and uv set index - COLLADAFW::IndexList& index_list = *index_list_array[uvset_index]; + COLLADAFW::IndexList& index_list = *index_list_array_uvcoord[uvset_index]; MLoopUV *mloopuv = (MLoopUV *)CustomData_get_layer_named(&me->ldata, CD_MLOOPUV, index_list.getName().c_str()); if (mloopuv == NULL) { - fprintf(stderr, "Collada import: Mesh [%s] : Unknown reference to TEXCOORD [#%s].", me->id.name, index_list.getName().c_str() ); + fprintf(stderr, "Collada import: Mesh [%s] : Unknown reference to TEXCOORD [#%s].\n", me->id.name, index_list.getName().c_str() ); } else { - set_face_uv(mloopuv+loop_index, uvs, start_index, *index_list_array[uvset_index], vcount); + set_face_uv(mloopuv+loop_index, uvs, start_index, *index_list_array_uvcoord[uvset_index], vcount); } } @@ -634,10 +708,23 @@ void MeshImporter::read_polys(COLLADAFW::Mesh *collada_mesh, Mesh *me) if (!is_flat_face(normal_indices, nor, vcount)) mpoly->flag |= ME_SMOOTH; } - + + for(unsigned int vcolor_index = 0 ; vcolor_index < index_list_array_vcolor.getCount();vcolor_index++) + { + COLLADAFW::IndexList& index_list = *index_list_array_vcolor[vcolor_index]; + COLLADAFW::String colname = extract_vcolname(index_list.getName()); + MLoopCol *mloopcol = (MLoopCol *)CustomData_get_layer_named(&me->ldata, CD_MLOOPCOL, colname.c_str()); + if (mloopcol == NULL) { + fprintf(stderr, "Collada import: Mesh [%s] : Unknown reference to VCOLOR [#%s].\n", me->id.name, index_list.getName().c_str() ); + } + else { + set_vcol(mloopcol+loop_index, vcol, start_index, *index_list_array_vcolor[vcolor_index], vcount); + } + } + mpoly++; - mloop += vcount; - loop_index += vcount; + mloop += vcount; + loop_index += vcount; start_index += vcount; prim.totpoly++; @@ -654,6 +741,8 @@ void MeshImporter::read_polys(COLLADAFW::Mesh *collada_mesh, Mesh *me) if (mp_has_faces) mat_prim_map[mp->getMaterialId()].push_back(prim); + + } geom_uid_mat_mapping_map[collada_mesh->getUniqueId()] = mat_prim_map; @@ -1114,5 +1203,6 @@ bool MeshImporter::write_geometry(const COLLADAFW::Geometry *geom) // read_lines() must be called after the face edges have been generated. // Oterwise the loose edges will be silently deleted again. read_lines(mesh, me); + return true; } diff --git a/source/blender/collada/MeshImporter.h b/source/blender/collada/MeshImporter.h index 5275420f4b5..9fc1d777f62 100644 --- a/source/blender/collada/MeshImporter.h +++ b/source/blender/collada/MeshImporter.h @@ -77,6 +77,14 @@ public: void getUV(int uv_index, float *uv); }; +class VCOLDataWrapper +{ + COLLADAFW::MeshVertexData *mVData; +public: + VCOLDataWrapper(COLLADAFW::MeshVertexData& vdata); + void get_vcol(int v_index, MLoopCol *mloopcol); +}; + class MeshImporter : public MeshImporterBase { private: @@ -113,6 +121,12 @@ private: COLLADAFW::IndexList& index_list, int count); + void set_vcol(MLoopCol *mloopcol, + VCOLDataWrapper &vob, + int loop_index, + COLLADAFW::IndexList& index_list, + int count); + #ifdef COLLADA_DEBUG void print_index_list(COLLADAFW::IndexList& index_list); #endif -- cgit v1.2.3