Blender  V3.3
abc_writer_mesh.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
7 #include "abc_writer_mesh.h"
10 
11 #include "BLI_assert.h"
12 #include "BLI_math_vector.h"
13 
14 #include "BKE_attribute.h"
15 #include "BKE_customdata.h"
16 #include "BKE_lib_id.h"
17 #include "BKE_material.h"
18 #include "BKE_mesh.h"
19 #include "BKE_modifier.h"
20 #include "BKE_object.h"
21 
22 #include "bmesh.h"
23 #include "bmesh_tools.h"
24 
25 #include "DEG_depsgraph.h"
26 
27 #include "DNA_layer_types.h"
28 #include "DNA_mesh_types.h"
29 #include "DNA_meshdata_types.h"
30 #include "DNA_modifier_types.h"
32 #include "DNA_particle_types.h"
33 
34 #include "CLG_log.h"
35 static CLG_LogRef LOG = {"io.alembic"};
36 
37 using Alembic::Abc::FloatArraySample;
38 using Alembic::Abc::Int32ArraySample;
39 using Alembic::Abc::OObject;
40 using Alembic::Abc::V2fArraySample;
41 using Alembic::Abc::V3fArraySample;
42 
43 using Alembic::AbcGeom::kFacevaryingScope;
44 using Alembic::AbcGeom::OBoolProperty;
45 using Alembic::AbcGeom::OCompoundProperty;
46 using Alembic::AbcGeom::OFaceSet;
47 using Alembic::AbcGeom::OFaceSetSchema;
48 using Alembic::AbcGeom::ON3fGeomParam;
49 using Alembic::AbcGeom::OPolyMesh;
50 using Alembic::AbcGeom::OPolyMeshSchema;
51 using Alembic::AbcGeom::OSubD;
52 using Alembic::AbcGeom::OSubDSchema;
53 using Alembic::AbcGeom::OV2fGeomParam;
54 using Alembic::AbcGeom::UInt32ArraySample;
55 
56 namespace blender::io::alembic {
57 
58 /* NOTE: Alembic's polygon winding order is clockwise, to match with Renderman. */
59 
60 static void get_vertices(struct Mesh *mesh, std::vector<Imath::V3f> &points);
61 static void get_topology(struct Mesh *mesh,
62  std::vector<int32_t> &poly_verts,
63  std::vector<int32_t> &loop_counts,
64  bool &r_has_flat_shaded_poly);
65 static void get_edge_creases(struct Mesh *mesh,
66  std::vector<int32_t> &indices,
67  std::vector<int32_t> &lengths,
68  std::vector<float> &sharpnesses);
69 static void get_vert_creases(struct Mesh *mesh,
70  std::vector<int32_t> &indices,
71  std::vector<float> &sharpnesses);
72 static void get_loop_normals(struct Mesh *mesh,
73  std::vector<Imath::V3f> &normals,
74  bool has_flat_shaded_poly);
75 
77  : ABCAbstractWriter(args), is_subd_(false)
78 {
79 }
80 
82 {
85  }
86 
87  if (is_subd_) {
88  CLOG_INFO(&LOG, 2, "exporting OSubD %s", args_.abc_path.c_str());
89  abc_subdiv_ = OSubD(args_.abc_parent, args_.abc_name, timesample_index_);
90  abc_subdiv_schema_ = abc_subdiv_.getSchema();
91  }
92  else {
93  CLOG_INFO(&LOG, 2, "exporting OPolyMesh %s", args_.abc_path.c_str());
94  abc_poly_mesh_ = OPolyMesh(args_.abc_parent, args_.abc_name, timesample_index_);
95  abc_poly_mesh_schema_ = abc_poly_mesh_.getSchema();
96 
97  OCompoundProperty typeContainer = abc_poly_mesh_.getSchema().getUserProperties();
98  OBoolProperty type(typeContainer, "meshtype");
99  type.set(subsurf_modifier_ == nullptr);
100  }
101 }
102 
103 Alembic::Abc::OObject ABCGenericMeshWriter::get_alembic_object() const
104 {
105  if (is_subd_) {
106  return abc_subdiv_;
107  }
108  return abc_poly_mesh_;
109 }
110 
111 Alembic::Abc::OCompoundProperty ABCGenericMeshWriter::abc_prop_for_custom_props()
112 {
113  if (is_subd_) {
114  return abc_schema_prop_for_custom_props(abc_subdiv_schema_);
115  }
116  return abc_schema_prop_for_custom_props(abc_poly_mesh_schema_);
117 }
118 
120 {
121  ModifierData *md = static_cast<ModifierData *>(ob_eval->modifiers.last);
122 
123  for (; md; md = md->prev) {
124  /* This modifier has been temporarily disabled by SubdivModifierDisabler,
125  * so this indicates this is to be exported as subdivision surface. */
127  return true;
128  }
129  }
130 
131  return false;
132 }
133 
135 {
137  return context->is_object_visible(args_.export_params->evaluation_mode);
138  }
139  return true;
140 }
141 
143 {
144  Object *object = context.object;
145  bool needsfree = false;
146 
147  Mesh *mesh = get_export_mesh(object, needsfree);
148 
149  if (mesh == nullptr) {
150  return;
151  }
152 
154  const bool tag_only = false;
155  const int quad_method = args_.export_params->quad_method;
156  const int ngon_method = args_.export_params->ngon_method;
157 
158  BMeshCreateParams bmesh_create_params{};
159  BMeshFromMeshParams bmesh_from_mesh_params{};
160  bmesh_from_mesh_params.calc_face_normal = true;
161  bmesh_from_mesh_params.calc_vert_normal = true;
162  BMesh *bm = BKE_mesh_to_bmesh_ex(mesh, &bmesh_create_params, &bmesh_from_mesh_params);
163 
164  BM_mesh_triangulate(bm, quad_method, ngon_method, 4, tag_only, nullptr, nullptr, nullptr);
165 
166  Mesh *triangulated_mesh = BKE_mesh_from_bmesh_for_eval_nomain(bm, nullptr, mesh);
167  BM_mesh_free(bm);
168 
169  if (needsfree) {
171  }
172  mesh = triangulated_mesh;
173  needsfree = true;
174  }
175 
176  m_custom_data_config.pack_uvs = args_.export_params->packuv;
177  m_custom_data_config.mesh = mesh;
178  m_custom_data_config.mpoly = mesh->mpoly;
179  m_custom_data_config.mloop = mesh->mloop;
180  m_custom_data_config.totpoly = mesh->totpoly;
181  m_custom_data_config.totloop = mesh->totloop;
182  m_custom_data_config.totvert = mesh->totvert;
183  m_custom_data_config.timesample_index = timesample_index_;
184 
185  try {
186  if (is_subd_) {
187  write_subd(context, mesh);
188  }
189  else {
190  write_mesh(context, mesh);
191  }
192 
193  if (needsfree) {
195  }
196  }
197  catch (...) {
198  if (needsfree) {
200  }
201  throw;
202  }
203 }
204 
206 {
207  BKE_id_free(nullptr, mesh);
208 }
209 
210 void ABCGenericMeshWriter::write_mesh(HierarchyContext &context, Mesh *mesh)
211 {
212  std::vector<Imath::V3f> points, normals;
213  std::vector<int32_t> poly_verts, loop_counts;
214  std::vector<Imath::V3f> velocities;
215  bool has_flat_shaded_poly = false;
216 
217  get_vertices(mesh, points);
218  get_topology(mesh, poly_verts, loop_counts, has_flat_shaded_poly);
219 
221  write_face_sets(context.object, mesh, abc_poly_mesh_schema_);
222  }
223 
224  OPolyMeshSchema::Sample mesh_sample = OPolyMeshSchema::Sample(
225  V3fArraySample(points), Int32ArraySample(poly_verts), Int32ArraySample(loop_counts));
226 
227  UVSample uvs_and_indices;
228 
229  if (args_.export_params->uvs) {
230  const char *name = get_uv_sample(uvs_and_indices, m_custom_data_config, &mesh->ldata);
231 
232  if (!uvs_and_indices.indices.empty() && !uvs_and_indices.uvs.empty()) {
233  OV2fGeomParam::Sample uv_sample;
234  uv_sample.setVals(V2fArraySample(uvs_and_indices.uvs));
235  uv_sample.setIndices(UInt32ArraySample(uvs_and_indices.indices));
236  uv_sample.setScope(kFacevaryingScope);
237 
238  abc_poly_mesh_schema_.setUVSourceName(name);
239  mesh_sample.setUVs(uv_sample);
240  }
241 
243  abc_poly_mesh_schema_.getArbGeomParams(), m_custom_data_config, &mesh->ldata, CD_MLOOPUV);
244  }
245 
246  if (args_.export_params->normals) {
247  get_loop_normals(mesh, normals, has_flat_shaded_poly);
248 
249  ON3fGeomParam::Sample normals_sample;
250  if (!normals.empty()) {
251  normals_sample.setScope(kFacevaryingScope);
252  normals_sample.setVals(V3fArraySample(normals));
253  }
254 
255  mesh_sample.setNormals(normals_sample);
256  }
257 
258  if (args_.export_params->orcos) {
259  write_generated_coordinates(abc_poly_mesh_schema_.getArbGeomParams(), m_custom_data_config);
260  }
261 
262  if (get_velocities(mesh, velocities)) {
263  mesh_sample.setVelocities(V3fArraySample(velocities));
264  }
265 
267  mesh_sample.setSelfBounds(bounding_box_);
268 
269  abc_poly_mesh_schema_.set(mesh_sample);
270 
271  write_arb_geo_params(mesh);
272 }
273 
274 void ABCGenericMeshWriter::write_subd(HierarchyContext &context, struct Mesh *mesh)
275 {
276  std::vector<float> edge_crease_sharpness, vert_crease_sharpness;
277  std::vector<Imath::V3f> points;
278  std::vector<int32_t> poly_verts, loop_counts;
279  std::vector<int32_t> edge_crease_indices, edge_crease_lengths, vert_crease_indices;
280  bool has_flat_poly = false;
281 
282  get_vertices(mesh, points);
283  get_topology(mesh, poly_verts, loop_counts, has_flat_poly);
284  get_edge_creases(mesh, edge_crease_indices, edge_crease_lengths, edge_crease_sharpness);
285  get_vert_creases(mesh, vert_crease_indices, vert_crease_sharpness);
286 
288  write_face_sets(context.object, mesh, abc_subdiv_schema_);
289  }
290 
291  OSubDSchema::Sample subdiv_sample = OSubDSchema::Sample(
292  V3fArraySample(points), Int32ArraySample(poly_verts), Int32ArraySample(loop_counts));
293 
294  UVSample sample;
295  if (args_.export_params->uvs) {
296  const char *name = get_uv_sample(sample, m_custom_data_config, &mesh->ldata);
297 
298  if (!sample.indices.empty() && !sample.uvs.empty()) {
299  OV2fGeomParam::Sample uv_sample;
300  uv_sample.setVals(V2fArraySample(sample.uvs));
301  uv_sample.setIndices(UInt32ArraySample(sample.indices));
302  uv_sample.setScope(kFacevaryingScope);
303 
304  abc_subdiv_schema_.setUVSourceName(name);
305  subdiv_sample.setUVs(uv_sample);
306  }
307 
309  abc_subdiv_schema_.getArbGeomParams(), m_custom_data_config, &mesh->ldata, CD_MLOOPUV);
310  }
311 
312  if (args_.export_params->orcos) {
313  write_generated_coordinates(abc_subdiv_schema_.getArbGeomParams(), m_custom_data_config);
314  }
315 
316  if (!edge_crease_indices.empty()) {
317  subdiv_sample.setCreaseIndices(Int32ArraySample(edge_crease_indices));
318  subdiv_sample.setCreaseLengths(Int32ArraySample(edge_crease_lengths));
319  subdiv_sample.setCreaseSharpnesses(FloatArraySample(edge_crease_sharpness));
320  }
321 
322  if (!vert_crease_indices.empty()) {
323  subdiv_sample.setCornerIndices(Int32ArraySample(vert_crease_indices));
324  subdiv_sample.setCornerSharpnesses(FloatArraySample(vert_crease_sharpness));
325  }
326 
328  subdiv_sample.setSelfBounds(bounding_box_);
329  abc_subdiv_schema_.set(subdiv_sample);
330 
331  write_arb_geo_params(mesh);
332 }
333 
334 template<typename Schema>
335 void ABCGenericMeshWriter::write_face_sets(Object *object, struct Mesh *mesh, Schema &schema)
336 {
337  std::map<std::string, std::vector<int32_t>> geo_groups;
338  get_geo_groups(object, mesh, geo_groups);
339 
340  std::map<std::string, std::vector<int32_t>>::iterator it;
341  for (it = geo_groups.begin(); it != geo_groups.end(); ++it) {
342  OFaceSet face_set = schema.createFaceSet(it->first);
343  OFaceSetSchema::Sample samp;
344  samp.setFaces(Int32ArraySample(it->second));
345  face_set.getSchema().set(samp);
346  }
347 }
348 
349 void ABCGenericMeshWriter::write_arb_geo_params(struct Mesh *me)
350 {
351  if (!args_.export_params->vcolors) {
352  return;
353  }
354 
355  OCompoundProperty arb_geom_params;
356  if (is_subd_) {
357  arb_geom_params = abc_subdiv_.getSchema().getArbGeomParams();
358  }
359  else {
360  arb_geom_params = abc_poly_mesh_.getSchema().getArbGeomParams();
361  }
362  write_custom_data(arb_geom_params, m_custom_data_config, &me->ldata, CD_PROP_BYTE_COLOR);
363 }
364 
365 bool ABCGenericMeshWriter::get_velocities(struct Mesh *mesh, std::vector<Imath::V3f> &vels)
366 {
367  /* Export velocity attribute output by fluid sim, sequence cache modifier
368  * and geometry nodes. */
369  CustomDataLayer *velocity_layer = BKE_id_attribute_find(
370  &mesh->id, "velocity", CD_PROP_FLOAT3, ATTR_DOMAIN_POINT);
371 
372  if (velocity_layer == nullptr) {
373  return false;
374  }
375 
376  const int totverts = mesh->totvert;
377  const float(*mesh_velocities)[3] = reinterpret_cast<float(*)[3]>(velocity_layer->data);
378 
379  vels.clear();
380  vels.resize(totverts);
381 
382  for (int i = 0; i < totverts; i++) {
383  copy_yup_from_zup(vels[i].getValue(), mesh_velocities[i]);
384  }
385 
386  return true;
387 }
388 
389 void ABCGenericMeshWriter::get_geo_groups(Object *object,
390  struct Mesh *mesh,
391  std::map<std::string, std::vector<int32_t>> &geo_groups)
392 {
393  const int num_poly = mesh->totpoly;
394  MPoly *polygons = mesh->mpoly;
395 
396  for (int i = 0; i < num_poly; i++) {
397  MPoly &current_poly = polygons[i];
398  short mnr = current_poly.mat_nr;
399 
400  Material *mat = BKE_object_material_get(object, mnr + 1);
401 
402  if (!mat) {
403  continue;
404  }
405 
406  std::string name = args_.hierarchy_iterator->get_id_name(&mat->id);
407 
408  if (geo_groups.find(name) == geo_groups.end()) {
409  std::vector<int32_t> faceArray;
410  geo_groups[name] = faceArray;
411  }
412 
413  geo_groups[name].push_back(i);
414  }
415 
416  if (geo_groups.empty()) {
417  Material *mat = BKE_object_material_get(object, 1);
418 
419  std::string name = (mat) ? args_.hierarchy_iterator->get_id_name(&mat->id) : "default";
420 
421  std::vector<int32_t> faceArray;
422 
423  for (int i = 0, e = mesh->totface; i < e; i++) {
424  faceArray.push_back(i);
425  }
426 
427  geo_groups[name] = faceArray;
428  }
429 }
430 
431 /* NOTE: Alembic's polygon winding order is clockwise, to match with Renderman. */
432 
433 static void get_vertices(struct Mesh *mesh, std::vector<Imath::V3f> &points)
434 {
435  points.clear();
436  points.resize(mesh->totvert);
437 
438  MVert *verts = mesh->mvert;
439 
440  for (int i = 0, e = mesh->totvert; i < e; i++) {
441  copy_yup_from_zup(points[i].getValue(), verts[i].co);
442  }
443 }
444 
445 static void get_topology(struct Mesh *mesh,
446  std::vector<int32_t> &poly_verts,
447  std::vector<int32_t> &loop_counts,
448  bool &r_has_flat_shaded_poly)
449 {
450  const int num_poly = mesh->totpoly;
451  const int num_loops = mesh->totloop;
452  MLoop *mloop = mesh->mloop;
453  MPoly *mpoly = mesh->mpoly;
454  r_has_flat_shaded_poly = false;
455 
456  poly_verts.clear();
457  loop_counts.clear();
458  poly_verts.reserve(num_loops);
459  loop_counts.reserve(num_poly);
460 
461  /* NOTE: data needs to be written in the reverse order. */
462  for (int i = 0; i < num_poly; i++) {
463  MPoly &poly = mpoly[i];
464  loop_counts.push_back(poly.totloop);
465 
466  r_has_flat_shaded_poly |= (poly.flag & ME_SMOOTH) == 0;
467 
468  MLoop *loop = mloop + poly.loopstart + (poly.totloop - 1);
469 
470  for (int j = 0; j < poly.totloop; j++, loop--) {
471  poly_verts.push_back(loop->v);
472  }
473  }
474 }
475 
476 static void get_edge_creases(struct Mesh *mesh,
477  std::vector<int32_t> &indices,
478  std::vector<int32_t> &lengths,
479  std::vector<float> &sharpnesses)
480 {
481  const float factor = 1.0f / 255.0f;
482 
483  indices.clear();
484  lengths.clear();
485  sharpnesses.clear();
486 
487  MEdge *edge = mesh->medge;
488 
489  for (int i = 0, e = mesh->totedge; i < e; i++) {
490  const float sharpness = static_cast<float>(edge[i].crease) * factor;
491 
492  if (sharpness != 0.0f) {
493  indices.push_back(edge[i].v1);
494  indices.push_back(edge[i].v2);
495  sharpnesses.push_back(sharpness);
496  }
497  }
498 
499  lengths.resize(sharpnesses.size(), 2);
500 }
501 
502 static void get_vert_creases(struct Mesh *mesh,
503  std::vector<int32_t> &indices,
504  std::vector<float> &sharpnesses)
505 {
506  indices.clear();
507  sharpnesses.clear();
508 
509  const float *creases = static_cast<const float *>(CustomData_get_layer(&mesh->vdata, CD_CREASE));
510 
511  if (!creases) {
512  return;
513  }
514 
515  for (int i = 0, v = mesh->totvert; i < v; i++) {
516  const float sharpness = creases[i];
517 
518  if (sharpness != 0.0f) {
519  indices.push_back(i);
520  sharpnesses.push_back(sharpness);
521  }
522  }
523 }
524 
525 static void get_loop_normals(struct Mesh *mesh,
526  std::vector<Imath::V3f> &normals,
527  bool has_flat_shaded_poly)
528 {
529  normals.clear();
530 
531  /* If all polygons are smooth shaded, and there are no custom normals, we don't need to export
532  * normals at all. This is also done by other software, see T71246. */
533  if (!has_flat_shaded_poly && !CustomData_has_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL) &&
534  (mesh->flag & ME_AUTOSMOOTH) == 0) {
535  return;
536  }
537 
539  const float(*lnors)[3] = static_cast<float(*)[3]>(CustomData_get_layer(&mesh->ldata, CD_NORMAL));
540  BLI_assert_msg(lnors != nullptr, "BKE_mesh_calc_normals_split() should have computed CD_NORMAL");
541 
542  normals.resize(mesh->totloop);
543 
544  /* NOTE: data needs to be written in the reverse order. */
545  int abc_index = 0;
546  MPoly *mp = mesh->mpoly;
547  for (int i = 0, e = mesh->totpoly; i < e; i++, mp++) {
548  for (int j = mp->totloop - 1; j >= 0; j--, abc_index++) {
549  int blender_index = mp->loopstart + j;
550  copy_yup_from_zup(normals[abc_index].getValue(), lnors[blender_index]);
551  }
552  }
553 }
554 
556 {
557 }
558 
559 Mesh *ABCMeshWriter::get_export_mesh(Object *object_eval, bool & /*r_needsfree*/)
560 {
561  return BKE_object_get_evaluated_mesh(object_eval);
562 }
563 
564 } // namespace blender::io::alembic
typedef float(TangentPoint)[2]
Generic geometry attributes built on CustomData.
@ ATTR_DOMAIN_POINT
Definition: BKE_attribute.h:27
struct CustomDataLayer * BKE_id_attribute_find(const struct ID *id, const char *name, int type, eAttrDomain domain)
CustomData interface, see also DNA_customdata_types.h.
bool CustomData_has_layer(const struct CustomData *data, int type)
void * CustomData_get_layer(const struct CustomData *data, int type)
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
struct BMesh * BKE_mesh_to_bmesh_ex(const struct Mesh *me, const struct BMeshCreateParams *create_params, const struct BMeshFromMeshParams *convert_params)
struct Mesh * BKE_mesh_from_bmesh_for_eval_nomain(struct BMesh *bm, const struct CustomData_MeshMasks *cd_mask_extra, const struct Mesh *me_settings)
void BKE_mesh_calc_normals_split(struct Mesh *mesh)
Definition: mesh.cc:1911
General operations, lookup, etc. for blender objects.
struct Mesh * BKE_object_get_evaluated_mesh(const struct Object *object)
#define BLI_assert_msg(a, msg)
Definition: BLI_assert.h:53
#define CLOG_INFO(clg_ref, level,...)
Definition: CLG_log.h:187
@ CD_PROP_BYTE_COLOR
@ CD_CUSTOMLOOPNORMAL
@ CD_PROP_FLOAT3
@ CD_MLOOPUV
@ ME_AUTOSMOOTH
@ ME_SMOOTH
@ eModifierMode_DisableTemporary
@ eModifierType_Subsurf
_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
_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 const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble v1
static CLG_LogRef LOG
ATTR_WARN_UNUSED_RESULT BMesh * bm
void BM_mesh_free(BMesh *bm)
BMesh Free Mesh.
Definition: bmesh_mesh.cc:258
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
void BM_mesh_triangulate(BMesh *bm, const int quad_method, const int ngon_method, const int min_vertices, const bool tag_only, BMOperator *op, BMOpSlot *slot_facemap_out, BMOpSlot *slot_facemap_double_out)
virtual std::string get_id_name(const ID *id) const
Alembic::Abc::OCompoundProperty abc_schema_prop_for_custom_props(T abc_schema)
const ABCWriterConstructorArgs args_
virtual void update_bounding_box(Object *object)
virtual void do_write(HierarchyContext &context) override
ABCGenericMeshWriter(const ABCWriterConstructorArgs &args)
virtual Alembic::Abc::OObject get_alembic_object() const override
virtual bool is_supported(const HierarchyContext *context) const override
virtual Mesh * get_export_mesh(Object *object_eval, bool &r_needsfree)=0
Alembic::Abc::OCompoundProperty abc_prop_for_custom_props() override
virtual void create_alembic_objects(const HierarchyContext *context) override
virtual bool export_as_subdivision_surface(Object *ob_eval) const
virtual Mesh * get_export_mesh(Object *object_eval, bool &r_needsfree) override
ABCMeshWriter(const ABCWriterConstructorArgs &args)
static float verts[][3]
ccl_gpu_kernel_postfix int ccl_global int * indices
BLI_INLINE void copy_yup_from_zup(float yup[3], const float zup[3])
static void get_topology(struct Mesh *mesh, std::vector< int32_t > &poly_verts, std::vector< int32_t > &loop_counts, bool &r_has_flat_shaded_poly)
const char * get_uv_sample(UVSample &sample, const CDStreamConfig &config, CustomData *data)
void write_custom_data(const OCompoundProperty &prop, CDStreamConfig &config, CustomData *data, int data_type)
static void get_loop_normals(struct Mesh *mesh, std::vector< Imath::V3f > &normals, bool has_flat_shaded_poly)
void write_generated_coordinates(const OCompoundProperty &prop, CDStreamConfig &config)
static void get_vertices(struct Mesh *mesh, std::vector< Imath::V3f > &points)
static void get_vert_creases(struct Mesh *mesh, std::vector< int32_t > &indices, std::vector< float > &sharpnesses)
static void get_edge_creases(struct Mesh *mesh, std::vector< int32_t > &indices, std::vector< int32_t > &lengths, std::vector< float > &sharpnesses)
MutableSpan< float3 > normals
SocketIndexByIdentifierMap * map
enum eEvaluationMode evaluation_mode
Definition: ABC_alembic.h:53
void * last
Definition: DNA_listBase.h:31
unsigned int v
short mat_nr
struct MEdge * medge
CustomData vdata
struct MVert * mvert
uint16_t flag
int totedge
int totvert
struct MLoop * mloop
int totface
int totpoly
int totloop
struct MPoly * mpoly
CustomData ldata
struct ModifierData * prev
ListBase modifiers