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