Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/io/collada/GeometryExporter.cpp')
-rw-r--r--source/blender/io/collada/GeometryExporter.cpp718
1 files changed, 718 insertions, 0 deletions
diff --git a/source/blender/io/collada/GeometryExporter.cpp b/source/blender/io/collada/GeometryExporter.cpp
new file mode 100644
index 00000000000..640bf3c0633
--- /dev/null
+++ b/source/blender/io/collada/GeometryExporter.cpp
@@ -0,0 +1,718 @@
+/*
+ * 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.
+ */
+
+/** \file
+ * \ingroup collada
+ */
+
+#include <sstream>
+
+#include "COLLADASWPrimitves.h"
+#include "COLLADASWSource.h"
+#include "COLLADASWVertices.h"
+#include "COLLADABUUtils.h"
+
+#include "GeometryExporter.h"
+
+#include "DNA_meshdata_types.h"
+
+extern "C" {
+#include "BLI_utildefines.h"
+
+#include "BKE_customdata.h"
+#include "BKE_global.h"
+#include "BKE_lib_id.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+}
+
+#include "collada_internal.h"
+#include "collada_utils.h"
+
+void GeometryExporter::exportGeom()
+{
+ Scene *sce = blender_context.get_scene();
+ openLibrary();
+
+ GeometryFunctor gf;
+ gf.forEachMeshObjectInExportSet<GeometryExporter>(
+ sce, *this, this->export_settings.get_export_set());
+
+ closeLibrary();
+}
+
+void GeometryExporter::operator()(Object *ob)
+{
+ bool use_instantiation = this->export_settings.get_use_object_instantiation();
+ Mesh *me = bc_get_mesh_copy(blender_context,
+ ob,
+ this->export_settings.get_export_mesh_type(),
+ this->export_settings.get_apply_modifiers(),
+ this->export_settings.get_triangulate());
+
+ std::string geom_id = get_geometry_id(ob, use_instantiation);
+ std::vector<Normal> nor;
+ std::vector<BCPolygonNormalsIndices> norind;
+
+ /* Skip if linked geometry was already exported from another reference */
+ if (use_instantiation && exportedGeometry.find(geom_id) != exportedGeometry.end()) {
+ return;
+ }
+
+ std::string geom_name = (use_instantiation) ? id_name(ob->data) : id_name(ob);
+ geom_name = encode_xml(geom_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->ldata, CD_MLOOPUV);
+
+ /* 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);
+
+ /* Only create Polylists if number of faces > 0 */
+ if (me->totface > 0) {
+ /* XXX slow */
+ if (ob->totcol) {
+ for (int a = 0; a < ob->totcol; a++) {
+ create_mesh_primitive_list(a, has_uvs, has_color, ob, me, geom_id, norind);
+ }
+ }
+ else {
+ create_mesh_primitive_list(0, has_uvs, has_color, ob, me, geom_id, norind);
+ }
+ }
+
+ closeMesh();
+
+ closeGeometry();
+
+ if (this->export_settings.get_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_keyblock_convert_to_mesh(kb, me);
+ export_key_mesh(ob, me, kb);
+ }
+ }
+ }
+
+ BKE_id_free(NULL, me);
+}
+
+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->ldata, CD_MLOOPUV);
+
+ /* 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++) {
+ create_mesh_primitive_list(a, has_uvs, has_color, ob, me, geom_id, norind);
+ }
+ }
+ else {
+ create_mesh_primitive_list(0, has_uvs, has_color, ob, me, geom_id, norind);
+ }
+
+ closeMesh();
+
+ closeGeometry();
+}
+
+void GeometryExporter::createLooseEdgeList(Object *ob, Mesh *me, std::string &geom_id)
+{
+
+ MEdge *medges = me->medge;
+ int totedges = me->totedge;
+ int edges_in_linelist = 0;
+ std::vector<unsigned int> edge_list;
+ int index;
+
+ /* Find all loose edges in Mesh
+ * and save vertex indices in edge_list */
+ for (index = 0; index < totedges; index++) {
+ MEdge *edge = &medges[index];
+
+ if (edge->flag & ME_LOOSEEDGE) {
+ edges_in_linelist += 1;
+ edge_list.push_back(edge->v1);
+ edge_list.push_back(edge->v2);
+ }
+ }
+
+ if (edges_in_linelist > 0) {
+ /* Create the list of loose edges */
+ COLLADASW::Lines lines(mSW);
+
+ lines.setCount(edges_in_linelist);
+
+ COLLADASW::InputList &til = lines.getInputList();
+
+ /* creates <input> in <lines> for vertices */
+ COLLADASW::Input input1(COLLADASW::InputSemantic::VERTEX,
+ getUrlBySemantics(geom_id, COLLADASW::InputSemantic::VERTEX),
+ 0);
+ til.push_back(input1);
+
+ lines.prepareToAppendValues();
+
+ for (index = 0; index < edges_in_linelist; index++) {
+ lines.appendValues(edge_list[2 * index + 1]);
+ lines.appendValues(edge_list[2 * index]);
+ }
+ lines.finish();
+ }
+}
+
+static void prepareToAppendValues(bool is_triangulated,
+ COLLADASW::PrimitivesBase &primitive_list,
+ std::vector<unsigned long> &vcount_list)
+{
+ /* performs the actual writing */
+ if (is_triangulated) {
+ ((COLLADASW::Triangles &)primitive_list).prepareToAppendValues();
+ }
+ else {
+ /* sets <vcount> */
+ primitive_list.setVCountList(vcount_list);
+ ((COLLADASW::Polylist &)primitive_list).prepareToAppendValues();
+ }
+}
+
+static void finish_and_delete_primitive_List(bool is_triangulated,
+ COLLADASW::PrimitivesBase *primitive_list)
+{
+ if (is_triangulated) {
+ ((COLLADASW::Triangles *)primitive_list)->finish();
+ }
+ else {
+ ((COLLADASW::Polylist *)primitive_list)->finish();
+ }
+ delete primitive_list;
+}
+
+static COLLADASW::PrimitivesBase *create_primitive_list(bool is_triangulated,
+ COLLADASW::StreamWriter *mSW)
+{
+ COLLADASW::PrimitivesBase *primitive_list;
+
+ if (is_triangulated) {
+ primitive_list = new COLLADASW::Triangles(mSW);
+ }
+ else {
+ primitive_list = new COLLADASW::Polylist(mSW);
+ }
+ return primitive_list;
+}
+
+static bool collect_vertex_counts_per_poly(Mesh *me,
+ int material_index,
+ std::vector<unsigned long> &vcount_list)
+{
+ MPoly *mpolys = me->mpoly;
+ int totpolys = me->totpoly;
+ bool is_triangulated = true;
+
+ int i;
+ /* Expecting that p->mat_nr is always 0 if the mesh has no materials assigned */
+ for (i = 0; i < totpolys; i++) {
+ MPoly *p = &mpolys[i];
+ if (p->mat_nr == material_index) {
+ int vertex_count = p->totloop;
+ vcount_list.push_back(vertex_count);
+ if (vertex_count != 3) {
+ is_triangulated = false;
+ }
+ }
+ }
+ return is_triangulated;
+}
+
+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::create_mesh_primitive_list(short material_index,
+ bool has_uvs,
+ bool has_color,
+ Object *ob,
+ Mesh *me,
+ std::string &geom_id,
+ std::vector<BCPolygonNormalsIndices> &norind)
+{
+
+ MPoly *mpolys = me->mpoly;
+ MLoop *mloops = me->mloop;
+ int totpolys = me->totpoly;
+
+ std::vector<unsigned long> vcount_list;
+
+ bool is_triangulated = collect_vertex_counts_per_poly(me, material_index, vcount_list);
+ int polygon_count = vcount_list.size();
+
+ /* no faces using this material */
+ if (polygon_count == 0) {
+ fprintf(
+ stderr, "%s: material with index %d is not used.\n", id_name(ob).c_str(), material_index);
+ return;
+ }
+
+ Material *ma = ob->totcol ? BKE_object_material_get(ob, material_index + 1) : NULL;
+ COLLADASW::PrimitivesBase *primitive_list = create_primitive_list(is_triangulated, mSW);
+
+ /* sets count attribute in <polylist> */
+ primitive_list->setCount(polygon_count);
+
+ /* sets material name */
+ if (ma) {
+ std::string material_id = get_material_id(ma);
+ std::ostringstream ostr;
+ ostr << translate_id(material_id);
+ primitive_list->setMaterial(ostr.str());
+ }
+
+ COLLADASW::Input vertex_input(COLLADASW::InputSemantic::VERTEX,
+ getUrlBySemantics(geom_id, COLLADASW::InputSemantic::VERTEX),
+ 0);
+ COLLADASW::Input normals_input(COLLADASW::InputSemantic::NORMAL,
+ getUrlBySemantics(geom_id, COLLADASW::InputSemantic::NORMAL),
+ 1);
+
+ COLLADASW::InputList &til = primitive_list->getInputList();
+ til.push_back(vertex_input);
+ til.push_back(normals_input);
+
+ /* if mesh has uv coords writes <input> for TEXCOORD */
+ int num_layers = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV);
+ int active_uv_index = CustomData_get_active_layer_index(&me->ldata, CD_MLOOPUV);
+ for (int i = 0; i < num_layers; i++) {
+ int layer_index = CustomData_get_layer_index_n(&me->ldata, CD_MLOOPUV, i);
+ if (!this->export_settings.get_active_uv_only() || layer_index == active_uv_index) {
+
+ // char *name = CustomData_get_layer_name(&me->ldata, CD_MLOOPUV, i);
+ COLLADASW::Input texcoord_input(
+ COLLADASW::InputSemantic::TEXCOORD,
+ makeUrl(makeTexcoordSourceId(geom_id, i, this->export_settings.get_active_uv_only())),
+ 2, // this is only until we have optimized UV sets
+ (this->export_settings.get_active_uv_only()) ? 0 : layer_index - 1 /* set (0,1,2,...) */
+ );
+ til.push_back(texcoord_input);
+ }
+ }
+
+ 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++;
+ }
+ }
+
+ /* performs the actual writing */
+ prepareToAppendValues(is_triangulated, *primitive_list, vcount_list);
+
+ /* <p> */
+ int texindex = 0;
+ for (int i = 0; i < totpolys; i++) {
+ MPoly *p = &mpolys[i];
+ int loop_count = p->totloop;
+
+ if (p->mat_nr == material_index) {
+ MLoop *l = &mloops[p->loopstart];
+ BCPolygonNormalsIndices normal_indices = norind[i];
+
+ for (int j = 0; j < loop_count; j++) {
+ primitive_list->appendValues(l[j].v);
+ primitive_list->appendValues(normal_indices[j]);
+ if (has_uvs) {
+ primitive_list->appendValues(texindex + j);
+ }
+
+ if (has_color) {
+ primitive_list->appendValues(texindex + j);
+ }
+ }
+ }
+
+ texindex += loop_count;
+ }
+
+ finish_and_delete_primitive_List(is_triangulated, primitive_list);
+}
+
+/* creates <source> for positions */
+void GeometryExporter::createVertsSource(std::string geom_id, Mesh *me)
+{
+#if 0
+ int totverts = dm->getNumVerts(dm);
+ MVert *verts = dm->getVertArray(dm);
+#endif
+ int totverts = me->totvert;
+ MVert *verts = me->mvert;
+
+ COLLADASW::FloatSourceF source(mSW);
+ source.setId(getIdBySemantics(geom_id, COLLADASW::InputSemantic::POSITION));
+ source.setArrayId(getIdBySemantics(geom_id, COLLADASW::InputSemantic::POSITION) +
+ ARRAY_ID_SUFFIX);
+ source.setAccessorCount(totverts);
+ source.setAccessorStride(3);
+
+ COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
+ param.push_back("X");
+ param.push_back("Y");
+ param.push_back("Z");
+ /* main function, it creates <source id = "">, <float_array id = ""
+ * count = ""> */
+ source.prepareToAppendValues();
+ /* appends data to <float_array> */
+ int i = 0;
+ for (i = 0; i < totverts; i++) {
+ Vector co;
+ if (export_settings.get_apply_global_orientation()) {
+ bc_add_global_transform(co, verts[i].co, export_settings.get_global_transform());
+ }
+ else {
+ copy_v3_v3(co, verts[i].co);
+ }
+ source.appendValues(co[0], co[1], co[2]);
+ }
+
+ source.finish();
+}
+
+void GeometryExporter::createVertexColorSource(std::string geom_id, Mesh *me)
+{
+ /* Find number of vertex color layers */
+ int totlayer_mcol = CustomData_number_of_layers(&me->ldata, CD_MLOOPCOL);
+ if (totlayer_mcol == 0) {
+ return;
+ }
+
+ int map_index = 0;
+ for (int a = 0; a < totlayer_mcol; a++) {
+
+ map_index++;
+ MLoopCol *mloopcol = (MLoopCol *)CustomData_get_layer_n(&me->ldata, CD_MLOOPCOL, a);
+
+ COLLADASW::FloatSourceF source(mSW);
+
+ 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(4);
+
+ COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
+ param.push_back("R");
+ param.push_back("G");
+ param.push_back("B");
+ param.push_back("A");
+
+ 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, mlc->a / 255.0f);
+ }
+ }
+
+ source.finish();
+ }
+}
+
+std::string GeometryExporter::makeTexcoordSourceId(std::string &geom_id,
+ int layer_index,
+ bool is_single_layer)
+{
+ char suffix[20];
+ if (is_single_layer) {
+ suffix[0] = '\0';
+ }
+ else {
+ sprintf(suffix, "-%d", layer_index);
+ }
+ return getIdBySemantics(geom_id, COLLADASW::InputSemantic::TEXCOORD) + suffix;
+}
+
+/* creates <source> for texcoords */
+void GeometryExporter::createTexcoordsSource(std::string geom_id, Mesh *me)
+{
+
+ int totpoly = me->totpoly;
+ int totuv = me->totloop;
+ MPoly *mpolys = me->mpoly;
+
+ 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 active_uv_index = CustomData_get_active_layer_index(&me->ldata, CD_MLOOPUV);
+ for (int a = 0; a < num_layers; a++) {
+ int layer_index = CustomData_get_layer_index_n(&me->ldata, CD_MLOOPUV, a);
+ if (!this->export_settings.get_active_uv_only() || layer_index == active_uv_index) {
+ MLoopUV *mloops = (MLoopUV *)CustomData_get_layer_n(&me->ldata, CD_MLOOPUV, a);
+
+ COLLADASW::FloatSourceF source(mSW);
+ std::string layer_id = makeTexcoordSourceId(
+ geom_id, a, this->export_settings.get_active_uv_only());
+ source.setId(layer_id);
+ source.setArrayId(layer_id + ARRAY_ID_SUFFIX);
+
+ source.setAccessorCount(totuv);
+ source.setAccessorStride(2);
+ COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
+ param.push_back("S");
+ param.push_back("T");
+
+ source.prepareToAppendValues();
+
+ 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]);
+ }
+ }
+
+ source.finish();
+ }
+ }
+}
+
+bool operator<(const Normal &a, const Normal &b)
+{
+ /* only needed to sort normal vectors and find() them later in a map.*/
+ return a.x < b.x || (a.x == b.x && (a.y < b.y || (a.y == b.y && a.z < b.z)));
+}
+
+/* creates <source> for normals */
+void GeometryExporter::createNormalsSource(std::string geom_id, Mesh *me, std::vector<Normal> &nor)
+{
+#if 0
+ int totverts = dm->getNumVerts(dm);
+ MVert *verts = dm->getVertArray(dm);
+#endif
+
+ COLLADASW::FloatSourceF source(mSW);
+ source.setId(getIdBySemantics(geom_id, COLLADASW::InputSemantic::NORMAL));
+ source.setArrayId(getIdBySemantics(geom_id, COLLADASW::InputSemantic::NORMAL) + ARRAY_ID_SUFFIX);
+ source.setAccessorCount((unsigned long)nor.size());
+ source.setAccessorStride(3);
+ COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
+ param.push_back("X");
+ param.push_back("Y");
+ param.push_back("Z");
+
+ source.prepareToAppendValues();
+
+ std::vector<Normal>::iterator it;
+ for (it = nor.begin(); it != nor.end(); it++) {
+ Normal &n = *it;
+
+ Vector no{n.x, n.y, n.z};
+ if (export_settings.get_apply_global_orientation()) {
+ bc_add_global_transform(no, export_settings.get_global_transform());
+ }
+ source.appendValues(no[0], no[1], no[2]);
+ }
+
+ source.finish();
+}
+
+void GeometryExporter::create_normals(std::vector<Normal> &normals,
+ std::vector<BCPolygonNormalsIndices> &polygons_normals,
+ Mesh *me)
+{
+ std::map<Normal, unsigned int> shared_normal_indices;
+ int last_normal_index = -1;
+
+ MVert *verts = me->mvert;
+ MLoop *mloops = me->mloop;
+ float(*lnors)[3] = NULL;
+ bool use_custom_normals = false;
+
+ BKE_mesh_calc_normals_split(me);
+ if (CustomData_has_layer(&me->ldata, CD_NORMAL)) {
+ lnors = (float(*)[3])CustomData_get_layer(&me->ldata, CD_NORMAL);
+ use_custom_normals = true;
+ }
+
+ for (int poly_index = 0; poly_index < me->totpoly; poly_index++) {
+ MPoly *mpoly = &me->mpoly[poly_index];
+ bool use_vertex_normals = use_custom_normals || mpoly->flag & ME_SMOOTH;
+
+ if (!use_vertex_normals) {
+ /* For flat faces use face normal as vertex normal: */
+
+ float vector[3];
+ BKE_mesh_calc_poly_normal(mpoly, mloops + mpoly->loopstart, verts, vector);
+
+ Normal n = {vector[0], vector[1], vector[2]};
+ normals.push_back(n);
+ last_normal_index++;
+ }
+
+ BCPolygonNormalsIndices poly_indices;
+ for (int loop_index = 0; loop_index < mpoly->totloop; loop_index++) {
+ unsigned int loop_idx = mpoly->loopstart + loop_index;
+ if (use_vertex_normals) {
+ float normalized[3];
+
+ if (use_custom_normals) {
+ normalize_v3_v3(normalized, lnors[loop_idx]);
+ }
+ else {
+ normal_short_to_float_v3(normalized, verts[mloops[loop_index].v].no);
+ normalize_v3(normalized);
+ }
+ Normal n = {normalized[0], normalized[1], normalized[2]};
+
+ if (shared_normal_indices.find(n) != shared_normal_indices.end()) {
+ poly_indices.add_index(shared_normal_indices[n]);
+ }
+ else {
+ last_normal_index++;
+ poly_indices.add_index(last_normal_index);
+ shared_normal_indices[n] = last_normal_index;
+ normals.push_back(n);
+ }
+ }
+ else {
+ poly_indices.add_index(last_normal_index);
+ }
+ }
+
+ polygons_normals.push_back(poly_indices);
+ }
+}
+
+std::string GeometryExporter::getIdBySemantics(std::string geom_id,
+ COLLADASW::InputSemantic::Semantics type,
+ std::string other_suffix)
+{
+ return geom_id + getSuffixBySemantic(type) + other_suffix;
+}
+
+COLLADASW::URI GeometryExporter::getUrlBySemantics(std::string geom_id,
+ COLLADASW::InputSemantic::Semantics type,
+ std::string other_suffix)
+{
+
+ std::string id(getIdBySemantics(geom_id, type, other_suffix));
+ return COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, id);
+}
+
+COLLADASW::URI GeometryExporter::makeUrl(std::string id)
+{
+ return COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, id);
+}