diff options
Diffstat (limited to 'source/blender/collada/GeometryExporter.cpp')
-rw-r--r-- | source/blender/collada/GeometryExporter.cpp | 328 |
1 files changed, 182 insertions, 146 deletions
diff --git a/source/blender/collada/GeometryExporter.cpp b/source/blender/collada/GeometryExporter.cpp index f33f0fa110d..669b787062a 100644 --- a/source/blender/collada/GeometryExporter.cpp +++ b/source/blender/collada/GeometryExporter.cpp @@ -53,10 +53,10 @@ extern "C" { #include "collada_utils.h" // TODO: optimize UV sets by making indexed list with duplicates removed -GeometryExporter::GeometryExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings) : COLLADASW::LibraryGeometries(sw), export_settings(export_settings) { +GeometryExporter::GeometryExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings) : COLLADASW::LibraryGeometries(sw), export_settings(export_settings) +{ } - void GeometryExporter::exportGeom(Scene *sce) { openLibrary(); @@ -69,26 +69,22 @@ void GeometryExporter::exportGeom(Scene *sce) } void GeometryExporter::operator()(Object *ob) -{ +{ // XXX don't use DerivedMesh, Mesh instead? - #if 0 DerivedMesh *dm = mesh_get_derived_final(mScene, ob, CD_MASK_BAREMESH); #endif bool use_instantiation = this->export_settings->use_object_instantiation; - Mesh *me; - if (this->export_settings->apply_modifiers) { - me = bc_to_mesh_apply_modifiers(mScene, ob, this->export_settings->export_mesh_type); - } - else { - me = (Mesh *)ob->data; - } - BKE_mesh_tessface_ensure(me); + Mesh *me = bc_get_mesh_copy( mScene, + ob, + this->export_settings->export_mesh_type, + this->export_settings->apply_modifiers, + this->export_settings->triangulate); std::string geom_id = get_geometry_id(ob, use_instantiation); std::vector<Normal> nor; - std::vector<Face> norind; + std::vector<BCPolygonNormalsIndices> norind; // Skip if linked geometry was already exported from another reference if (use_instantiation && @@ -117,12 +113,13 @@ void GeometryExporter::operator()(Object *ob) bool has_uvs = (bool)CustomData_has_layer(&me->fdata, CD_MTFACE); // writes <source> for uv coords if mesh has uv coords - if (has_uvs) + if (has_uvs) { createTexcoordsSource(geom_id, me); + } - if (has_color) + if (has_color) { createVertexColorSource(geom_id, me); - + } // <vertices> COLLADASW::Vertices verts(mSW); @@ -132,7 +129,7 @@ void GeometryExporter::operator()(Object *ob) input_list.push_back(input); verts.add(); - createLooseEdgeList(ob, me, geom_id, norind); + createLooseEdgeList(ob, me, geom_id); // Only create Polylists if number of faces > 0 if (me->totface > 0) { @@ -155,22 +152,95 @@ void GeometryExporter::operator()(Object *ob) closeGeometry(); - if (this->export_settings->apply_modifiers) - { - BKE_libblock_free_us(&(G.main->mesh), me); + if (this->export_settings->include_shapekeys) { + Key * key = BKE_key_from_object(ob); + if (key) { + KeyBlock * kb = (KeyBlock *)key->block.first; + //skip the basis + kb = kb->next; + for (; kb; kb = kb->next) { + BKE_key_convert_to_mesh(kb, me); + export_key_mesh(ob, me, kb); + } + } } + BKE_libblock_free_us(&(G.main->mesh), me); -#if 0 - dm->release(dm); -#endif } +void GeometryExporter::export_key_mesh(Object *ob, Mesh *me, KeyBlock *kb) +{ + std::string geom_id = get_geometry_id(ob, false) + "_morph_" + translate_id(kb->name); + std::vector<Normal> nor; + std::vector<BCPolygonNormalsIndices> norind; + + if (exportedGeometry.find(geom_id) != exportedGeometry.end()) + { + return; + } + + std::string geom_name = kb->name; + + exportedGeometry.insert(geom_id); + + bool has_color = (bool)CustomData_has_layer(&me->fdata, CD_MCOL); + + create_normals(nor, norind, me); + + // openMesh(geoId, geoName, meshId) + openMesh(geom_id, geom_name); + + // writes <source> for vertex coords + createVertsSource(geom_id, me); + + // writes <source> for normal coords + createNormalsSource(geom_id, me, nor); + + bool has_uvs = (bool)CustomData_has_layer(&me->fdata, CD_MTFACE); + + // writes <source> for uv coords if mesh has uv coords + if (has_uvs) { + createTexcoordsSource(geom_id, me); + } + + if (has_color) { + createVertexColorSource(geom_id, me); + } + + // <vertices> + + COLLADASW::Vertices verts(mSW); + verts.setId(getIdBySemantics(geom_id, COLLADASW::InputSemantic::VERTEX)); + COLLADASW::InputList &input_list = verts.getInputList(); + COLLADASW::Input input(COLLADASW::InputSemantic::POSITION, getUrlBySemantics(geom_id, COLLADASW::InputSemantic::POSITION)); + input_list.push_back(input); + verts.add(); + + //createLooseEdgeList(ob, me, geom_id, norind); + + // XXX slow + if (ob->totcol) { + for (int a = 0; a < ob->totcol; a++) { + createPolylist(a, has_uvs, has_color, ob, me, geom_id, norind); + } + } + else { + createPolylist(0, has_uvs, has_color, ob, me, geom_id, norind); + } + + closeMesh(); + + if (me->flag & ME_TWOSIDED) { + mSW->appendTextBlock("<extra><technique profile=\"MAYA\"><double_sided>1</double_sided></technique></extra>"); + } + + closeGeometry(); +} void GeometryExporter::createLooseEdgeList(Object *ob, Mesh *me, - std::string& geom_id, - std::vector<Face>& norind) + std::string& geom_id) { MEdge *medges = me->medge; @@ -226,10 +296,12 @@ void GeometryExporter::createPolylist(short material_index, Object *ob, Mesh *me, std::string& geom_id, - std::vector<Face>& norind) + std::vector<BCPolygonNormalsIndices>& norind) { - MFace *mfaces = me->mface; - int totfaces = me->totface; + + MPoly *mpolys = me->mpoly; + MLoop *mloops = me->mloop; + int totpolys = me->totpoly; // <vcount> int i; @@ -237,17 +309,12 @@ void GeometryExporter::createPolylist(short material_index, std::vector<unsigned long> vcount_list; // count faces with this material - for (i = 0; i < totfaces; i++) { - MFace *f = &mfaces[i]; + for (i = 0; i < totpolys; i++) { + MPoly *p = &mpolys[i]; - if (f->mat_nr == material_index) { + if (p->mat_nr == material_index) { faces_in_polylist++; - if (f->v4 == 0) { - vcount_list.push_back(3); - } - else { - vcount_list.push_back(4); - } + vcount_list.push_back(p->totloop); } } @@ -309,21 +376,19 @@ void GeometryExporter::createPolylist(short material_index, // performs the actual writing polylist.prepareToAppendValues(); - - // <p> int texindex = 0; - for (i = 0; i < totfaces; i++) { - MFace *f = &mfaces[i]; + for (i = 0; i < totpolys; i++) { + MPoly *p = &mpolys[i]; + int loop_count = p->totloop; - if (f->mat_nr == material_index) { - - unsigned int *v = &f->v1; - unsigned int *n = &norind[i].v1; - for (int j = 0; j < (f->v4 == 0 ? 3 : 4); j++) { - polylist.appendValues(v[j]); - polylist.appendValues(n[j]); + if (p->mat_nr == material_index) { + MLoop *l = &mloops[p->loopstart]; + BCPolygonNormalsIndices normal_indices = norind[i]; + for (int j = 0; j < loop_count; j++) { + polylist.appendValues(l[j].v); + polylist.appendValues(normal_indices[j]); if (has_uvs) polylist.appendValues(texindex + j); @@ -332,14 +397,13 @@ void GeometryExporter::createPolylist(short material_index, } } - texindex += 3; - if (f->v4 != 0) - texindex++; + texindex += loop_count; } polylist.finish(); } + // creates <source> for positions void GeometryExporter::createVertsSource(std::string geom_id, Mesh *me) { @@ -375,19 +439,14 @@ void GeometryExporter::createVertsSource(std::string geom_id, Mesh *me) void GeometryExporter::createVertexColorSource(std::string geom_id, Mesh *me) { - if (!CustomData_has_layer(&me->fdata, CD_MCOL)) + if (!CustomData_has_layer(&me->ldata, CD_MLOOPCOL)) return; - MFace *f; - int totcolor = 0, i, j; - - for (i = 0, f = me->mface; i < me->totface; i++, f++) - totcolor += f->v4 ? 4 : 3; 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(totcolor); + source.setAccessorCount(me->totloop); source.setAccessorStride(3); COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); @@ -397,18 +456,26 @@ void GeometryExporter::createVertexColorSource(std::string geom_id, Mesh *me) source.prepareToAppendValues(); - int index = CustomData_get_active_layer_index(&me->fdata, CD_MCOL); - - MCol *mcol = (MCol *)me->fdata.layers[index].data; - MCol *c = mcol; + int index = CustomData_get_active_layer_index(&me->ldata, CD_MLOOPCOL); + MCol *mcol = (MCol *)me->ldata.layers[index].data; - for (i = 0, f = me->mface; i < me->totface; i++, c += 4, f++) - for (j = 0; j < (f->v4 ? 4 : 3); j++) - source.appendValues(c[j].b / 255.0f, c[j].g / 255.0f, c[j].r / 255.0f); + MPoly *mpoly; + int i; + for (i = 0, mpoly = me->mpoly; i < me->totpoly; i++, mpoly++) { + MCol *color = mcol + mpoly->loopstart; + for (int j = 0; j < mpoly->totloop; j++, color++) { + source.appendValues( + color->b / 255.0f, + color->g / 255.0f, + color->r / 255.0f + ); + } + } source.finish(); } + std::string GeometryExporter::makeTexcoordSourceId(std::string& geom_id, int layer_index) { char suffix[20]; @@ -419,38 +486,21 @@ std::string GeometryExporter::makeTexcoordSourceId(std::string& geom_id, int lay //creates <source> for texcoords void GeometryExporter::createTexcoordsSource(std::string geom_id, Mesh *me) { -#if 0 - int totfaces = dm->getNumTessFaces(dm); - MFace *mfaces = dm->getTessFaceArray(dm); -#endif - int totfaces = me->totface; - MFace *mfaces = me->mface; - - int totuv = 0; - int i; - // count totuv - for (i = 0; i < totfaces; i++) { - MFace *f = &mfaces[i]; - if (f->v4 == 0) { - totuv += 3; - } - else { - totuv += 4; - } - } + int totpoly = me->totpoly; + int totuv = me->totloop; + MPoly *mpolys = me->mpoly; - int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE); + int num_layers = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV); // write <source> for each layer // each <source> will get id like meshName + "map-channel-1" int map_index = 0; - int active_uv_index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE)-1; + int active_uv_index = CustomData_get_active_layer_index(&me->ldata, CD_MLOOPUV); for (int a = 0; a < num_layers; a++) { if (!this->export_settings->active_uv_only || a == active_uv_index) { - MTFace *tface = (MTFace *)CustomData_get_layer_n(&me->fdata, CD_MTFACE, a); - // char *name = CustomData_get_layer_name(&me->fdata, CD_MTFACE, a); + MLoopUV *mloops = (MLoopUV *)CustomData_get_layer_n(&me->ldata, CD_MLOOPUV, a); COLLADASW::FloatSourceF source(mSW); std::string layer_id = makeTexcoordSourceId(geom_id, map_index++); @@ -465,12 +515,12 @@ void GeometryExporter::createTexcoordsSource(std::string geom_id, Mesh *me) source.prepareToAppendValues(); - for (i = 0; i < totfaces; i++) { - MFace *f = &mfaces[i]; - - for (int j = 0; j < (f->v4 == 0 ? 3 : 4); j++) { - source.appendValues(tface[i].uv[j][0], - tface[i].uv[j][1]); + for (int index = 0; index < totpoly; index++) { + MPoly *mpoly = mpolys+index; + MLoopUV *mloop = mloops+mpoly->loopstart; + for (int j = 0; j < mpoly->totloop; j++) { + source.appendValues(mloop[j].uv[0], + mloop[j].uv[1]); } } @@ -510,53 +560,54 @@ void GeometryExporter::createNormalsSource(std::string geom_id, Mesh *me, std::v source.finish(); } -void GeometryExporter::create_normals(std::vector<Normal> &nor, std::vector<Face> &ind, Mesh *me) +void GeometryExporter::create_normals(std::vector<Normal> &normals, std::vector<BCPolygonNormalsIndices> &polygons_normals, Mesh *me) { - int i, j, v; - MVert *vert = me->mvert; - std::map<unsigned int, unsigned int> nshar; - - for (i = 0; i < me->totface; i++) { - MFace *fa = &me->mface[i]; - Face f; - unsigned int *nn = &f.v1; - unsigned int *vv = &fa->v1; - - memset(&f, 0, sizeof(f)); - v = fa->v4 == 0 ? 3 : 4; - - if (!(fa->flag & ME_SMOOTH)) { - Normal n; - if (v == 4) - normal_quad_v3(&n.x, vert[fa->v1].co, vert[fa->v2].co, vert[fa->v3].co, vert[fa->v4].co); - else - normal_tri_v3(&n.x, vert[fa->v1].co, vert[fa->v2].co, vert[fa->v3].co); - nor.push_back(n); + std::map<unsigned int, unsigned int> shared_normal_indices; + int last_normal_index = -1; + + MVert *verts = me->mvert; + MLoop *mloops = me->mloop; + for (int poly_index = 0; poly_index < me->totpoly; poly_index++) { + MPoly *mpoly = &me->mpoly[poly_index]; + + if (!(mpoly->flag & ME_SMOOTH)) { + // For flat faces use face normal as vertex normal: + + float vector[3]; + BKE_mesh_calc_poly_normal(mpoly, mloops, verts, vector); + + Normal n = { vector[0], vector[1], vector[2] }; + normals.push_back(n); + last_normal_index++; } - for (j = 0; j < v; j++) { - if (fa->flag & ME_SMOOTH) { - if (nshar.find(*vv) != nshar.end()) - *nn = nshar[*vv]; + + MLoop *mloop = mloops + mpoly->loopstart; + BCPolygonNormalsIndices poly_indices; + for (int loop_index = 0; loop_index < mpoly->totloop; loop_index++) { + unsigned int vertex_index = mloop[loop_index].v; + if (mpoly->flag & ME_SMOOTH) { + if (shared_normal_indices.find(vertex_index) != shared_normal_indices.end()) + poly_indices.add_index (shared_normal_indices[vertex_index]); else { - Normal n = { - (float)vert[*vv].no[0] / 32767.0f, - (float)vert[*vv].no[1] / 32767.0f, - (float)vert[*vv].no[2] / 32767.0f - }; - nor.push_back(n); - *nn = (unsigned int)nor.size() - 1; - nshar[*vv] = *nn; + + float vector[3]; + normal_short_to_float_v3(vector, verts[vertex_index].no); + + Normal n = { vector[0], vector[1], vector[2] }; + normals.push_back(n); + last_normal_index++; + + poly_indices.add_index(last_normal_index); + shared_normal_indices[vertex_index] = last_normal_index; } - vv++; } else { - *nn = (unsigned int)nor.size() - 1; + poly_indices.add_index(last_normal_index); } - nn++; } - ind.push_back(f); + polygons_normals.push_back(poly_indices); } } @@ -579,19 +630,4 @@ COLLADASW::URI GeometryExporter::makeUrl(std::string id) return COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, id); } -#if 0 -int GeometryExporter::getTriCount(MFace *faces, int totface) -{ - int i; - int tris = 0; - for (i = 0; i < totface; i++) { - // if quad - if (faces[i].v4 != 0) - tris += 2; - else - tris++; - } - return tris; -} -#endif |