1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License
4 * as published by the Free Software Foundation; either version 2
5 * of the License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software Foundation,
14 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15 */
16
17 /** \file
18 * \ingroup collada
19 */
20
21 #include <sstream>
22
23 #include "COLLADABUUtils.h"
24 #include "COLLADASWPrimitves.h"
25 #include "COLLADASWSource.h"
26 #include "COLLADASWVertices.h"
27
28 #include "GeometryExporter.h"
29
30 #include "DNA_meshdata_types.h"
31
32 #include "BLI_utildefines.h"
33
34 #include "BKE_customdata.h"
35 #include "BKE_global.h"
36 #include "BKE_lib_id.h"
37 #include "BKE_material.h"
38 #include "BKE_mesh.h"
39
40 #include "collada_internal.h"
41 #include "collada_utils.h"
42
exportGeom()43 void GeometryExporter::exportGeom()
44 {
45 Scene *sce = blender_context.get_scene();
46 openLibrary();
47
48 GeometryFunctor gf;
49 gf.forEachMeshObjectInExportSet<GeometryExporter>(
50 sce, *this, this->export_settings.get_export_set());
51
52 closeLibrary();
53 }
54
operator ()(Object * ob)55 void GeometryExporter::operator()(Object *ob)
56 {
57 bool use_instantiation = this->export_settings.get_use_object_instantiation();
58 Mesh *me = bc_get_mesh_copy(blender_context,
59 ob,
60 this->export_settings.get_export_mesh_type(),
61 this->export_settings.get_apply_modifiers(),
62 this->export_settings.get_triangulate());
63
64 std::string geom_id = get_geometry_id(ob, use_instantiation);
65 std::vector<Normal> nor;
66 std::vector<BCPolygonNormalsIndices> norind;
67
68 /* Skip if linked geometry was already exported from another reference */
69 if (use_instantiation && exportedGeometry.find(geom_id) != exportedGeometry.end()) {
70 return;
71 }
72
73 std::string geom_name = (use_instantiation) ? id_name(ob->data) : id_name(ob);
74 geom_name = encode_xml(geom_name);
75
76 exportedGeometry.insert(geom_id);
77
78 bool has_color = (bool)CustomData_has_layer(&me->fdata, CD_MCOL);
79
80 create_normals(nor, norind, me);
81
82 /* openMesh(geoId, geoName, meshId) */
83 openMesh(geom_id, geom_name);
84
85 /* writes <source> for vertex coords */
86 createVertsSource(geom_id, me);
87
88 /* writes <source> for normal coords */
89 createNormalsSource(geom_id, me, nor);
90
91 bool has_uvs = (bool)CustomData_has_layer(&me->ldata, CD_MLOOPUV);
92
93 /* writes <source> for uv coords if mesh has uv coords */
94 if (has_uvs) {
95 createTexcoordsSource(geom_id, me);
96 }
97
98 if (has_color) {
99 createVertexColorSource(geom_id, me);
100 }
101 /* <vertices> */
102
103 COLLADASW::Vertices verts(mSW);
104 verts.setId(getIdBySemantics(geom_id, COLLADASW::InputSemantic::VERTEX));
105 COLLADASW::InputList &input_list = verts.getInputList();
106 COLLADASW::Input input(COLLADASW::InputSemantic::POSITION,
107 getUrlBySemantics(geom_id, COLLADASW::InputSemantic::POSITION));
108 input_list.push_back(input);
109 verts.add();
110
111 createLooseEdgeList(ob, me, geom_id);
112
113 /* Only create Polylists if number of faces > 0 */
114 if (me->totface > 0) {
115 /* XXX slow */
116 if (ob->totcol) {
117 for (int a = 0; a < ob->totcol; a++) {
118 create_mesh_primitive_list(a, has_uvs, has_color, ob, me, geom_id, norind);
119 }
120 }
121 else {
122 create_mesh_primitive_list(0, has_uvs, has_color, ob, me, geom_id, norind);
123 }
124 }
125
126 closeMesh();
127
128 closeGeometry();
129
130 if (this->export_settings.get_include_shapekeys()) {
131 Key *key = BKE_key_from_object(ob);
132 if (key) {
133 KeyBlock *kb = (KeyBlock *)key->block.first;
134 /* skip the basis */
135 kb = kb->next;
136 for (; kb; kb = kb->next) {
137 BKE_keyblock_convert_to_mesh(kb, me);
138 export_key_mesh(ob, me, kb);
139 }
140 }
141 }
142
143 BKE_id_free(NULL, me);
144 }
145
export_key_mesh(Object * ob,Mesh * me,KeyBlock * kb)146 void GeometryExporter::export_key_mesh(Object *ob, Mesh *me, KeyBlock *kb)
147 {
148 std::string geom_id = get_geometry_id(ob, false) + "_morph_" + translate_id(kb->name);
149 std::vector<Normal> nor;
150 std::vector<BCPolygonNormalsIndices> norind;
151
152 if (exportedGeometry.find(geom_id) != exportedGeometry.end()) {
153 return;
154 }
155
156 std::string geom_name = kb->name;
157
158 exportedGeometry.insert(geom_id);
159
160 bool has_color = (bool)CustomData_has_layer(&me->fdata, CD_MCOL);
161
162 create_normals(nor, norind, me);
163
164 // openMesh(geoId, geoName, meshId)
165 openMesh(geom_id, geom_name);
166
167 /* writes <source> for vertex coords */
168 createVertsSource(geom_id, me);
169
170 /* writes <source> for normal coords */
171 createNormalsSource(geom_id, me, nor);
172
173 bool has_uvs = (bool)CustomData_has_layer(&me->ldata, CD_MLOOPUV);
174
175 /* writes <source> for uv coords if mesh has uv coords */
176 if (has_uvs) {
177 createTexcoordsSource(geom_id, me);
178 }
179
180 if (has_color) {
181 createVertexColorSource(geom_id, me);
182 }
183
184 /* <vertices> */
185
186 COLLADASW::Vertices verts(mSW);
187 verts.setId(getIdBySemantics(geom_id, COLLADASW::InputSemantic::VERTEX));
188 COLLADASW::InputList &input_list = verts.getInputList();
189 COLLADASW::Input input(COLLADASW::InputSemantic::POSITION,
190 getUrlBySemantics(geom_id, COLLADASW::InputSemantic::POSITION));
191 input_list.push_back(input);
192 verts.add();
193
194 // createLooseEdgeList(ob, me, geom_id, norind);
195
196 /* XXX slow */
197 if (ob->totcol) {
198 for (int a = 0; a < ob->totcol; a++) {
199 create_mesh_primitive_list(a, has_uvs, has_color, ob, me, geom_id, norind);
200 }
201 }
202 else {
203 create_mesh_primitive_list(0, has_uvs, has_color, ob, me, geom_id, norind);
204 }
205
206 closeMesh();
207
208 closeGeometry();
209 }
210
createLooseEdgeList(Object * ob,Mesh * me,std::string & geom_id)211 void GeometryExporter::createLooseEdgeList(Object *ob, Mesh *me, std::string &geom_id)
212 {
213
214 MEdge *medges = me->medge;
215 int totedges = me->totedge;
216 int edges_in_linelist = 0;
217 std::vector<unsigned int> edge_list;
218 int index;
219
220 /* Find all loose edges in Mesh
221 * and save vertex indices in edge_list */
222 for (index = 0; index < totedges; index++) {
223 MEdge *edge = &medges[index];
224
225 if (edge->flag & ME_LOOSEEDGE) {
226 edges_in_linelist += 1;
227 edge_list.push_back(edge->v1);
228 edge_list.push_back(edge->v2);
229 }
230 }
231
232 if (edges_in_linelist > 0) {
233 /* Create the list of loose edges */
234 COLLADASW::Lines lines(mSW);
235
236 lines.setCount(edges_in_linelist);
237
238 COLLADASW::InputList &til = lines.getInputList();
239
240 /* creates <input> in <lines> for vertices */
241 COLLADASW::Input input1(COLLADASW::InputSemantic::VERTEX,
242 getUrlBySemantics(geom_id, COLLADASW::InputSemantic::VERTEX),
243 0);
244 til.push_back(input1);
245
246 lines.prepareToAppendValues();
247
248 for (index = 0; index < edges_in_linelist; index++) {
249 lines.appendValues(edge_list[2 * index + 1]);
250 lines.appendValues(edge_list[2 * index]);
251 }
252 lines.finish();
253 }
254 }
255
prepareToAppendValues(bool is_triangulated,COLLADASW::PrimitivesBase & primitive_list,std::vector<unsigned long> & vcount_list)256 static void prepareToAppendValues(bool is_triangulated,
257 COLLADASW::PrimitivesBase &primitive_list,
258 std::vector<unsigned long> &vcount_list)
259 {
260 /* performs the actual writing */
261 if (is_triangulated) {
262 ((COLLADASW::Triangles &)primitive_list).prepareToAppendValues();
263 }
264 else {
265 /* sets <vcount> */
266 primitive_list.setVCountList(vcount_list);
267 ((COLLADASW::Polylist &)primitive_list).prepareToAppendValues();
268 }
269 }
270
finish_and_delete_primitive_List(bool is_triangulated,COLLADASW::PrimitivesBase * primitive_list)271 static void finish_and_delete_primitive_List(bool is_triangulated,
272 COLLADASW::PrimitivesBase *primitive_list)
273 {
274 if (is_triangulated) {
275 ((COLLADASW::Triangles *)primitive_list)->finish();
276 }
277 else {
278 ((COLLADASW::Polylist *)primitive_list)->finish();
279 }
280 delete primitive_list;
281 }
282
create_primitive_list(bool is_triangulated,COLLADASW::StreamWriter * mSW)283 static COLLADASW::PrimitivesBase *create_primitive_list(bool is_triangulated,
284 COLLADASW::StreamWriter *mSW)
285 {
286 COLLADASW::PrimitivesBase *primitive_list;
287
288 if (is_triangulated) {
289 primitive_list = new COLLADASW::Triangles(mSW);
290 }
291 else {
292 primitive_list = new COLLADASW::Polylist(mSW);
293 }
294 return primitive_list;
295 }
296
collect_vertex_counts_per_poly(Mesh * me,int material_index,std::vector<unsigned long> & vcount_list)297 static bool collect_vertex_counts_per_poly(Mesh *me,
298 int material_index,
299 std::vector<unsigned long> &vcount_list)
300 {
301 MPoly *mpolys = me->mpoly;
302 int totpolys = me->totpoly;
303 bool is_triangulated = true;
304
305 int i;
306 /* Expecting that p->mat_nr is always 0 if the mesh has no materials assigned */
307 for (i = 0; i < totpolys; i++) {
308 MPoly *p = &mpolys[i];
309 if (p->mat_nr == material_index) {
310 int vertex_count = p->totloop;
311 vcount_list.push_back(vertex_count);
312 if (vertex_count != 3) {
313 is_triangulated = false;
314 }
315 }
316 }
317 return is_triangulated;
318 }
319
makeVertexColorSourceId(std::string & geom_id,char * layer_name)320 std::string GeometryExporter::makeVertexColorSourceId(std::string &geom_id, char *layer_name)
321 {
322 std::string result = getIdBySemantics(geom_id, COLLADASW::InputSemantic::COLOR) + "-" +
323 layer_name;
324 return result;
325 }
326
327 /* powerful because it handles both cases when there is material and when there's not */
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)328 void GeometryExporter::create_mesh_primitive_list(short material_index,
329 bool has_uvs,
330 bool has_color,
331 Object *ob,
332 Mesh *me,
333 std::string &geom_id,
334 std::vector<BCPolygonNormalsIndices> &norind)
335 {
336
337 MPoly *mpolys = me->mpoly;
338 MLoop *mloops = me->mloop;
339 int totpolys = me->totpoly;
340
341 std::vector<unsigned long> vcount_list;
342
343 bool is_triangulated = collect_vertex_counts_per_poly(me, material_index, vcount_list);
344 int polygon_count = vcount_list.size();
345
346 /* no faces using this material */
347 if (polygon_count == 0) {
348 fprintf(
349 stderr, "%s: material with index %d is not used.\n", id_name(ob).c_str(), material_index);
350 return;
351 }
352
353 Material *ma = ob->totcol ? BKE_object_material_get(ob, material_index + 1) : NULL;
354 COLLADASW::PrimitivesBase *primitive_list = create_primitive_list(is_triangulated, mSW);
355
356 /* sets count attribute in <polylist> */
357 primitive_list->setCount(polygon_count);
358
359 /* sets material name */
360 if (ma) {
361 std::string material_id = get_material_id(ma);
362 std::ostringstream ostr;
363 ostr << translate_id(material_id);
364 primitive_list->setMaterial(ostr.str());
365 }
366
367 COLLADASW::Input vertex_input(COLLADASW::InputSemantic::VERTEX,
368 getUrlBySemantics(geom_id, COLLADASW::InputSemantic::VERTEX),
369 0);
370 COLLADASW::Input normals_input(COLLADASW::InputSemantic::NORMAL,
371 getUrlBySemantics(geom_id, COLLADASW::InputSemantic::NORMAL),
372 1);
373
374 COLLADASW::InputList &til = primitive_list->getInputList();
375 til.push_back(vertex_input);
376 til.push_back(normals_input);
377
378 /* if mesh has uv coords writes <input> for TEXCOORD */
379 int num_layers = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV);
380 int active_uv_index = CustomData_get_active_layer_index(&me->ldata, CD_MLOOPUV);
381 for (int i = 0; i < num_layers; i++) {
382 int layer_index = CustomData_get_layer_index_n(&me->ldata, CD_MLOOPUV, i);
383 if (!this->export_settings.get_active_uv_only() || layer_index == active_uv_index) {
384
385 // char *name = CustomData_get_layer_name(&me->ldata, CD_MLOOPUV, i);
386 COLLADASW::Input texcoord_input(
387 COLLADASW::InputSemantic::TEXCOORD,
388 makeUrl(makeTexcoordSourceId(geom_id, i, this->export_settings.get_active_uv_only())),
389 2, /* this is only until we have optimized UV sets */
390 (this->export_settings.get_active_uv_only()) ? 0 : layer_index - 1 /* set (0,1,2,...) */
391 );
392 til.push_back(texcoord_input);
393 }
394 }
395
396 int totlayer_mcol = CustomData_number_of_layers(&me->ldata, CD_MLOOPCOL);
397 if (totlayer_mcol > 0) {
398 int map_index = 0;
399
400 for (int a = 0; a < totlayer_mcol; a++) {
401 char *layer_name = bc_CustomData_get_layer_name(&me->ldata, CD_MLOOPCOL, a);
402 COLLADASW::Input input4(COLLADASW::InputSemantic::COLOR,
403 makeUrl(makeVertexColorSourceId(geom_id, layer_name)),
404 (has_uvs) ? 3 : 2, /* all color layers have same index order */
405 map_index /* set number equals color map index */
406 );
407 til.push_back(input4);
408 map_index++;
409 }
410 }
411
412 /* performs the actual writing */
413 prepareToAppendValues(is_triangulated, *primitive_list, vcount_list);
414
415 /* <p> */
416 int texindex = 0;
417 for (int i = 0; i < totpolys; i++) {
418 MPoly *p = &mpolys[i];
419 int loop_count = p->totloop;
420
421 if (p->mat_nr == material_index) {
422 MLoop *l = &mloops[p->loopstart];
423 BCPolygonNormalsIndices normal_indices = norind[i];
424
425 for (int j = 0; j < loop_count; j++) {
426 primitive_list->appendValues(l[j].v);
427 primitive_list->appendValues(normal_indices[j]);
428 if (has_uvs) {
429 primitive_list->appendValues(texindex + j);
430 }
431
432 if (has_color) {
433 primitive_list->appendValues(texindex + j);
434 }
435 }
436 }
437
438 texindex += loop_count;
439 }
440
441 finish_and_delete_primitive_List(is_triangulated, primitive_list);
442 }
443
444 /* creates <source> for positions */
createVertsSource(std::string geom_id,Mesh * me)445 void GeometryExporter::createVertsSource(std::string geom_id, Mesh *me)
446 {
447 #if 0
448 int totverts = dm->getNumVerts(dm);
449 MVert *verts = dm->getVertArray(dm);
450 #endif
451 int totverts = me->totvert;
452 MVert *verts = me->mvert;
453
454 COLLADASW::FloatSourceF source(mSW);
455 source.setId(getIdBySemantics(geom_id, COLLADASW::InputSemantic::POSITION));
456 source.setArrayId(getIdBySemantics(geom_id, COLLADASW::InputSemantic::POSITION) +
457 ARRAY_ID_SUFFIX);
458 source.setAccessorCount(totverts);
459 source.setAccessorStride(3);
460
461 COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList();
462 param.push_back("X");
463 param.push_back("Y");
464 param.push_back("Z");
465 /* main function, it creates <source id = "">, <float_array id = ""
466 * count = ""> */
467 source.prepareToAppendValues();
468 /* appends data to <float_array> */
469 int i = 0;
470 for (i = 0; i < totverts; i++) {
471 Vector co;
472 if (export_settings.get_apply_global_orientation()) {
473 bc_add_global_transform(co, verts[i].co, export_settings.get_global_transform());
474 }
475 else {
476 copy_v3_v3(co, verts[i].co);
477 }
478 source.appendValues(co[0], co[1], co[2]);
479 }
480
481 source.finish();
482 }
483
createVertexColorSource(std::string geom_id,Mesh * me)484 void GeometryExporter::createVertexColorSource(std::string geom_id, Mesh *me)
485 {
486 /* Find number of vertex color layers */
487 int totlayer_mcol = CustomData_number_of_layers(&me->ldata, CD_MLOOPCOL);
488 if (totlayer_mcol == 0) {
489 return;
490 }
491
492 int map_index = 0;
493 for (int a = 0; a < totlayer_mcol; a++) {
494
495 map_index++;
496 MLoopCol *mloopcol = (MLoopCol *)CustomData_get_layer_n(&me->ldata, CD_MLOOPCOL, a);
497
498 COLLADASW::FloatSourceF source(mSW);
499
500 char *layer_name = bc_CustomData_get_layer_name(&me->ldata, CD_MLOOPCOL, a);
501 std::string layer_id = makeVertexColorSourceId(geom_id, layer_name);
502 source.setId(layer_id);
503
504 source.setNodeName(layer_name);
505
506 source.setArrayId(layer_id + ARRAY_ID_SUFFIX);
507 source.setAccessorCount(me->totloop);
508 source.setAccessorStride(4);
509
510 COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList();
511 param.push_back("R");
512 param.push_back("G");
513 param.push_back("B");
514 param.push_back("A");
515
516 source.prepareToAppendValues();
517
518 MPoly *mpoly;
519 int i;
520 for (i = 0, mpoly = me->mpoly; i < me->totpoly; i++, mpoly++) {
521 MLoopCol *mlc = mloopcol + mpoly->loopstart;
522 for (int j = 0; j < mpoly->totloop; j++, mlc++) {
523 source.appendValues(mlc->r / 255.0f, mlc->g / 255.0f, mlc->b / 255.0f, mlc->a / 255.0f);
524 }
525 }
526
527 source.finish();
528 }
529 }
530
makeTexcoordSourceId(std::string & geom_id,int layer_index,bool is_single_layer)531 std::string GeometryExporter::makeTexcoordSourceId(std::string &geom_id,
532 int layer_index,
533 bool is_single_layer)
534 {
535 char suffix[20];
536 if (is_single_layer) {
537 suffix[0] = '\0';
538 }
539 else {
540 sprintf(suffix, "-%d", layer_index);
541 }
542 return getIdBySemantics(geom_id, COLLADASW::InputSemantic::TEXCOORD) + suffix;
543 }
544
545 /* creates <source> for texcoords */
createTexcoordsSource(std::string geom_id,Mesh * me)546 void GeometryExporter::createTexcoordsSource(std::string geom_id, Mesh *me)
547 {
548
549 int totpoly = me->totpoly;
550 int totuv = me->totloop;
551 MPoly *mpolys = me->mpoly;
552
553 int num_layers = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV);
554
555 /* write <source> for each layer
556 * each <source> will get id like meshName + "map-channel-1" */
557 int active_uv_index = CustomData_get_active_layer_index(&me->ldata, CD_MLOOPUV);
558 for (int a = 0; a < num_layers; a++) {
559 int layer_index = CustomData_get_layer_index_n(&me->ldata, CD_MLOOPUV, a);
560 if (!this->export_settings.get_active_uv_only() || layer_index == active_uv_index) {
561 MLoopUV *mloops = (MLoopUV *)CustomData_get_layer_n(&me->ldata, CD_MLOOPUV, a);
562
563 COLLADASW::FloatSourceF source(mSW);
564 std::string layer_id = makeTexcoordSourceId(
565 geom_id, a, this->export_settings.get_active_uv_only());
566 source.setId(layer_id);
567 source.setArrayId(layer_id + ARRAY_ID_SUFFIX);
568
569 source.setAccessorCount(totuv);
570 source.setAccessorStride(2);
571 COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList();
572 param.push_back("S");
573 param.push_back("T");
574
575 source.prepareToAppendValues();
576
577 for (int index = 0; index < totpoly; index++) {
578 MPoly *mpoly = mpolys + index;
579 MLoopUV *mloop = mloops + mpoly->loopstart;
580 for (int j = 0; j < mpoly->totloop; j++) {
581 source.appendValues(mloop[j].uv[0], mloop[j].uv[1]);
582 }
583 }
584
585 source.finish();
586 }
587 }
588 }
589
operator <(const Normal & a,const Normal & b)590 bool operator<(const Normal &a, const Normal &b)
591 {
592 /* only needed to sort normal vectors and find() them later in a map.*/
593 return a.x < b.x || (a.x == b.x && (a.y < b.y || (a.y == b.y && a.z < b.z)));
594 }
595
596 /* creates <source> for normals */
createNormalsSource(std::string geom_id,Mesh * me,std::vector<Normal> & nor)597 void GeometryExporter::createNormalsSource(std::string geom_id, Mesh *me, std::vector<Normal> &nor)
598 {
599 #if 0
600 int totverts = dm->getNumVerts(dm);
601 MVert *verts = dm->getVertArray(dm);
602 #endif
603
604 COLLADASW::FloatSourceF source(mSW);
605 source.setId(getIdBySemantics(geom_id, COLLADASW::InputSemantic::NORMAL));
606 source.setArrayId(getIdBySemantics(geom_id, COLLADASW::InputSemantic::NORMAL) + ARRAY_ID_SUFFIX);
607 source.setAccessorCount((unsigned long)nor.size());
608 source.setAccessorStride(3);
609 COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList();
610 param.push_back("X");
611 param.push_back("Y");
612 param.push_back("Z");
613
614 source.prepareToAppendValues();
615
616 std::vector<Normal>::iterator it;
617 for (it = nor.begin(); it != nor.end(); it++) {
618 Normal &n = *it;
619
620 Vector no{n.x, n.y, n.z};
621 if (export_settings.get_apply_global_orientation()) {
622 bc_add_global_transform(no, export_settings.get_global_transform());
623 }
624 source.appendValues(no[0], no[1], no[2]);
625 }
626
627 source.finish();
628 }
629
create_normals(std::vector<Normal> & normals,std::vector<BCPolygonNormalsIndices> & polygons_normals,Mesh * me)630 void GeometryExporter::create_normals(std::vector<Normal> &normals,
631 std::vector<BCPolygonNormalsIndices> &polygons_normals,
632 Mesh *me)
633 {
634 std::map<Normal, unsigned int> shared_normal_indices;
635 int last_normal_index = -1;
636
637 MVert *verts = me->mvert;
638 MLoop *mloops = me->mloop;
639 float(*lnors)[3] = NULL;
640 bool use_custom_normals = false;
641
642 BKE_mesh_calc_normals_split(me);
643 if (CustomData_has_layer(&me->ldata, CD_NORMAL)) {
644 lnors = (float(*)[3])CustomData_get_layer(&me->ldata, CD_NORMAL);
645 use_custom_normals = true;
646 }
647
648 for (int poly_index = 0; poly_index < me->totpoly; poly_index++) {
649 MPoly *mpoly = &me->mpoly[poly_index];
650 bool use_vertex_normals = use_custom_normals || mpoly->flag & ME_SMOOTH;
651
652 if (!use_vertex_normals) {
653 /* For flat faces use face normal as vertex normal: */
654
655 float vector[3];
656 BKE_mesh_calc_poly_normal(mpoly, mloops + mpoly->loopstart, verts, vector);
657
658 Normal n = {vector[0], vector[1], vector[2]};
659 normals.push_back(n);
660 last_normal_index++;
661 }
662
663 BCPolygonNormalsIndices poly_indices;
664 for (int loop_index = 0; loop_index < mpoly->totloop; loop_index++) {
665 unsigned int loop_idx = mpoly->loopstart + loop_index;
666 if (use_vertex_normals) {
667 float normalized[3];
668
669 if (use_custom_normals) {
670 normalize_v3_v3(normalized, lnors[loop_idx]);
671 }
672 else {
673 normal_short_to_float_v3(normalized, verts[mloops[loop_index].v].no);
674 normalize_v3(normalized);
675 }
676 Normal n = {normalized[0], normalized[1], normalized[2]};
677
678 if (shared_normal_indices.find(n) != shared_normal_indices.end()) {
679 poly_indices.add_index(shared_normal_indices[n]);
680 }
681 else {
682 last_normal_index++;
683 poly_indices.add_index(last_normal_index);
684 shared_normal_indices[n] = last_normal_index;
685 normals.push_back(n);
686 }
687 }
688 else {
689 poly_indices.add_index(last_normal_index);
690 }
691 }
692
693 polygons_normals.push_back(poly_indices);
694 }
695 }
696
getIdBySemantics(std::string geom_id,COLLADASW::InputSemantic::Semantics type,std::string other_suffix)697 std::string GeometryExporter::getIdBySemantics(std::string geom_id,
698 COLLADASW::InputSemantic::Semantics type,
699 std::string other_suffix)
700 {
701 return geom_id + getSuffixBySemantic(type) + other_suffix;
702 }
703
getUrlBySemantics(std::string geom_id,COLLADASW::InputSemantic::Semantics type,std::string other_suffix)704 COLLADASW::URI GeometryExporter::getUrlBySemantics(std::string geom_id,
705 COLLADASW::InputSemantic::Semantics type,
706 std::string other_suffix)
707 {
708
709 std::string id(getIdBySemantics(geom_id, type, other_suffix));
710 return COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, id);
711 }
712
makeUrl(std::string id)713 COLLADASW::URI GeometryExporter::makeUrl(std::string id)
714 {
715 return COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, id);
716 }
717