Modifiers: add minimum number of vertices to triangulate modifier.
[blender.git] / source / blender / alembic / intern / abc_mesh.cc
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 balembic
19  */
20
21 #include "abc_mesh.h"
22
23 #include <algorithm>
24
25 #include "abc_transform.h"
26 #include "abc_util.h"
27
28 extern "C" {
29 #include "DNA_material_types.h"
30 #include "DNA_mesh_types.h"
31 #include "DNA_meshdata_types.h"
32 #include "DNA_modifier_types.h"
33 #include "DNA_object_fluidsim_types.h"
34 #include "DNA_object_types.h"
35
36 #include "BLI_math_geom.h"
37 #include "BLI_string.h"
38
39 #include "BKE_animsys.h"
40 #include "BKE_key.h"
41 #include "BKE_library.h"
42 #include "BKE_main.h"
43 #include "BKE_material.h"
44 #include "BKE_mesh.h"
45 #include "BKE_mesh_runtime.h"
46 #include "BKE_modifier.h"
47 #include "BKE_object.h"
48
49 #include "WM_api.h"
50 #include "WM_types.h"
51
52 #include "ED_mesh.h"
53
54 #include "bmesh.h"
55 #include "bmesh_tools.h"
56
57 #include "DEG_depsgraph_query.h"
58 }
59
60 using Alembic::Abc::FloatArraySample;
61 using Alembic::Abc::ICompoundProperty;
62 using Alembic::Abc::Int32ArraySample;
63 using Alembic::Abc::Int32ArraySamplePtr;
64 using Alembic::Abc::P3fArraySamplePtr;
65 using Alembic::Abc::V2fArraySample;
66 using Alembic::Abc::V3fArraySample;
67 using Alembic::Abc::C4fArraySample;
68
69 using Alembic::AbcGeom::IFaceSet;
70 using Alembic::AbcGeom::IFaceSetSchema;
71 using Alembic::AbcGeom::IObject;
72 using Alembic::AbcGeom::IPolyMesh;
73 using Alembic::AbcGeom::IPolyMeshSchema;
74 using Alembic::AbcGeom::ISampleSelector;
75 using Alembic::AbcGeom::ISubD;
76 using Alembic::AbcGeom::ISubDSchema;
77 using Alembic::AbcGeom::IV2fGeomParam;
78
79 using Alembic::AbcGeom::OArrayProperty;
80 using Alembic::AbcGeom::OBoolProperty;
81 using Alembic::AbcGeom::OC3fArrayProperty;
82 using Alembic::AbcGeom::OC3fGeomParam;
83 using Alembic::AbcGeom::OC4fGeomParam;
84 using Alembic::AbcGeom::OCompoundProperty;
85 using Alembic::AbcGeom::OFaceSet;
86 using Alembic::AbcGeom::OFaceSetSchema;
87 using Alembic::AbcGeom::OFloatGeomParam;
88 using Alembic::AbcGeom::OInt32GeomParam;
89 using Alembic::AbcGeom::ON3fArrayProperty;
90 using Alembic::AbcGeom::ON3fGeomParam;
91 using Alembic::AbcGeom::OPolyMesh;
92 using Alembic::AbcGeom::OPolyMeshSchema;
93 using Alembic::AbcGeom::OSubD;
94 using Alembic::AbcGeom::OSubDSchema;
95 using Alembic::AbcGeom::OV2fGeomParam;
96 using Alembic::AbcGeom::OV3fGeomParam;
97
98 using Alembic::AbcGeom::kFacevaryingScope;
99 using Alembic::AbcGeom::kVaryingScope;
100 using Alembic::AbcGeom::kVertexScope;
101 using Alembic::AbcGeom::kWrapExisting;
102 using Alembic::AbcGeom::UInt32ArraySample;
103 using Alembic::AbcGeom::N3fArraySamplePtr;
104 using Alembic::AbcGeom::IN3fGeomParam;
105
106 /* ************************************************************************** */
107
108 /* NOTE: Alembic's polygon winding order is clockwise, to match with Renderman. */
109
110 static void get_vertices(struct Mesh *mesh, std::vector<Imath::V3f> &points)
111 {
112         points.clear();
113         points.resize(mesh->totvert);
114
115         MVert *verts = mesh->mvert;
116
117         for (int i = 0, e = mesh->totvert; i < e; ++i) {
118                 copy_yup_from_zup(points[i].getValue(), verts[i].co);
119         }
120 }
121
122 static void get_topology(struct Mesh *mesh,
123                          std::vector<int32_t> &poly_verts,
124                          std::vector<int32_t> &loop_counts,
125                          bool &smooth_normal)
126 {
127         const int num_poly = mesh->totpoly;
128         const int num_loops = mesh->totloop;
129         MLoop *mloop = mesh->mloop;
130         MPoly *mpoly = mesh->mpoly;
131
132         poly_verts.clear();
133         loop_counts.clear();
134         poly_verts.reserve(num_loops);
135         loop_counts.reserve(num_poly);
136
137         /* NOTE: data needs to be written in the reverse order. */
138         for (int i = 0; i < num_poly; ++i) {
139                 MPoly &poly = mpoly[i];
140                 loop_counts.push_back(poly.totloop);
141
142                 smooth_normal |= ((poly.flag & ME_SMOOTH) != 0);
143
144                 MLoop *loop = mloop + poly.loopstart + (poly.totloop - 1);
145
146                 for (int j = 0; j < poly.totloop; ++j, --loop) {
147                         poly_verts.push_back(loop->v);
148                 }
149         }
150 }
151
152 static void get_creases(struct Mesh *mesh,
153                         std::vector<int32_t> &indices,
154                         std::vector<int32_t> &lengths,
155                         std::vector<float> &sharpnesses)
156 {
157         const float factor = 1.0f / 255.0f;
158
159         indices.clear();
160         lengths.clear();
161         sharpnesses.clear();
162
163         MEdge *edge = mesh->medge;
164
165         for (int i = 0, e = mesh->totedge; i < e; ++i) {
166                 const float sharpness = static_cast<float>(edge[i].crease) * factor;
167
168                 if (sharpness != 0.0f) {
169                         indices.push_back(edge[i].v1);
170                         indices.push_back(edge[i].v2);
171                         sharpnesses.push_back(sharpness);
172                 }
173         }
174
175         lengths.resize(sharpnesses.size(), 2);
176 }
177
178 static void get_vertex_normals(struct Mesh *mesh, std::vector<Imath::V3f> &normals)
179 {
180         normals.clear();
181         normals.resize(mesh->totvert);
182
183         MVert *verts = mesh->mvert;
184         float no[3];
185
186         for (int i = 0, e = mesh->totvert; i < e; ++i) {
187                 normal_short_to_float_v3(no, verts[i].no);
188                 copy_yup_from_zup(normals[i].getValue(), no);
189         }
190 }
191
192 static void get_loop_normals(struct Mesh *mesh, std::vector<Imath::V3f> &normals)
193 {
194         MPoly *mp = mesh->mpoly;
195
196         MLoop *mloop = mesh->mloop;
197         MLoop *ml = mloop;
198
199         MVert *verts = mesh->mvert;
200
201         const float (*lnors)[3] = static_cast<float(*)[3]>(CustomData_get_layer(&mesh->ldata, CD_NORMAL));
202
203         normals.clear();
204         normals.resize(mesh->totloop);
205
206         unsigned loop_index = 0;
207
208         /* NOTE: data needs to be written in the reverse order. */
209
210         if (lnors) {
211                 for (int i = 0, e = mesh->totpoly; i < e; ++i, ++mp) {
212                         ml = mloop + mp->loopstart + (mp->totloop - 1);
213
214                         for (int j = 0; j < mp->totloop; --ml, ++j, ++loop_index) {
215                                 const int index = ml->v;
216                                 copy_yup_from_zup(normals[loop_index].getValue(), lnors[index]);
217                         }
218                 }
219         }
220         else {
221                 float no[3];
222
223                 for (int i = 0, e = mesh->totpoly; i < e; ++i, ++mp) {
224                         ml = mloop + mp->loopstart + (mp->totloop - 1);
225
226                         /* Flat shaded, use common normal for all verts. */
227                         if ((mp->flag & ME_SMOOTH) == 0) {
228                                 BKE_mesh_calc_poly_normal(mp, ml - (mp->totloop - 1), verts, no);
229
230                                 for (int j = 0; j < mp->totloop; --ml, ++j, ++loop_index) {
231                                         copy_yup_from_zup(normals[loop_index].getValue(), no);
232                                 }
233                         }
234                         else {
235                                 /* Smooth shaded, use individual vert normals. */
236                                 for (int j = 0; j < mp->totloop; --ml, ++j, ++loop_index) {
237                                         normal_short_to_float_v3(no, verts[ml->v].no);
238                                         copy_yup_from_zup(normals[loop_index].getValue(), no);
239                                 }
240                         }
241                 }
242         }
243 }
244
245 /* *************** Modifiers *************** */
246
247 /* check if the mesh is a subsurf, ignoring disabled modifiers and
248  * displace if it's after subsurf. */
249 static ModifierData *get_subsurf_modifier(Scene *scene, Object *ob)
250 {
251         ModifierData *md = static_cast<ModifierData *>(ob->modifiers.last);
252
253         for (; md; md = md->prev) {
254                 if (!modifier_isEnabled(scene, md, eModifierMode_Render)) {
255                         continue;
256                 }
257
258                 if (md->type == eModifierType_Subsurf) {
259                         SubsurfModifierData *smd = reinterpret_cast<SubsurfModifierData*>(md);
260
261                         if (smd->subdivType == ME_CC_SUBSURF) {
262                                 return md;
263                         }
264                 }
265
266                 /* mesh is not a subsurf. break */
267                 if ((md->type != eModifierType_Displace) && (md->type != eModifierType_ParticleSystem)) {
268                         return NULL;
269                 }
270         }
271
272         return NULL;
273 }
274
275 static ModifierData *get_liquid_sim_modifier(Scene *scene, Object *ob)
276 {
277         ModifierData *md = modifiers_findByType(ob, eModifierType_Fluidsim);
278
279         if (md && (modifier_isEnabled(scene, md, eModifierMode_Render))) {
280                 FluidsimModifierData *fsmd = reinterpret_cast<FluidsimModifierData *>(md);
281
282                 if (fsmd->fss && fsmd->fss->type == OB_FLUIDSIM_DOMAIN) {
283                         return md;
284                 }
285         }
286
287         return NULL;
288 }
289
290 /* ************************************************************************** */
291
292 AbcGenericMeshWriter::AbcGenericMeshWriter(Object *ob,
293                                            AbcTransformWriter *parent,
294                                            uint32_t time_sampling,
295                                            ExportSettings &settings)
296     : AbcObjectWriter(ob, time_sampling, settings, parent)
297 {
298         m_is_animated = isAnimated();
299         m_subsurf_mod = NULL;
300         m_is_subd = false;
301
302         /* If the object is static, use the default static time sampling. */
303         if (!m_is_animated) {
304                 time_sampling = 0;
305         }
306
307         if (!m_settings.apply_subdiv) {
308                 m_subsurf_mod = get_subsurf_modifier(m_settings.scene, m_object);
309                 m_is_subd = (m_subsurf_mod != NULL);
310         }
311
312         m_is_liquid = (get_liquid_sim_modifier(m_settings.scene, m_object) != NULL);
313
314         while (parent->alembicXform().getChildHeader(m_name)) {
315                 m_name.append("_");
316         }
317
318         if (m_settings.use_subdiv_schema && m_is_subd) {
319                 OSubD subd(parent->alembicXform(), m_name, m_time_sampling);
320                 m_subdiv_schema = subd.getSchema();
321         }
322         else {
323                 OPolyMesh mesh(parent->alembicXform(), m_name, m_time_sampling);
324                 m_mesh_schema = mesh.getSchema();
325
326                 OCompoundProperty typeContainer = m_mesh_schema.getUserProperties();
327                 OBoolProperty type(typeContainer, "meshtype");
328                 type.set(m_is_subd);
329         }
330 }
331
332 AbcGenericMeshWriter::~AbcGenericMeshWriter()
333 {
334         if (m_subsurf_mod) {
335                 m_subsurf_mod->mode &= ~eModifierMode_DisableTemporary;
336         }
337 }
338
339 bool AbcGenericMeshWriter::isAnimated() const
340 {
341         if (m_object->data != NULL) {
342                 AnimData *adt = BKE_animdata_from_id(static_cast<ID*>(m_object->data));
343                 /* TODO(Sybren): make this check more strict, as the AnimationData may
344                  * actually be empty (no fcurves, drivers, etc.) and thus effectively
345                  * have no animation at all. */
346                 if (adt != NULL) {
347                         return true;
348                 }
349         }
350         if (BKE_key_from_object(m_object) != NULL) {
351                 return true;
352         }
353
354         /* Test modifiers. */
355         ModifierData *md = static_cast<ModifierData *>(m_object->modifiers.first);
356         while (md) {
357
358                 if (md->type != eModifierType_Subsurf) {
359                         return true;
360                 }
361
362                 md = md->next;
363         }
364
365         return false;
366 }
367
368 void AbcGenericMeshWriter::setIsAnimated(bool is_animated)
369 {
370         m_is_animated = is_animated;
371 }
372
373 void AbcGenericMeshWriter::do_write()
374 {
375         /* We have already stored a sample for this object. */
376         if (!m_first_frame && !m_is_animated)
377                 return;
378
379         bool needsfree;
380         struct Mesh *mesh = getFinalMesh(needsfree);
381
382         try {
383                 if (m_settings.use_subdiv_schema && m_subdiv_schema.valid()) {
384                         writeSubD(mesh);
385                 }
386                 else {
387                         writeMesh(mesh);
388                 }
389
390                 if (needsfree) BKE_id_free(NULL, mesh);
391         }
392         catch (...) {
393                 if (needsfree) BKE_id_free(NULL, mesh);
394                 throw;
395         }
396 }
397
398 void AbcGenericMeshWriter::writeMesh(struct Mesh *mesh)
399 {
400         std::vector<Imath::V3f> points, normals;
401         std::vector<int32_t> poly_verts, loop_counts;
402
403         bool smooth_normal = false;
404
405         get_vertices(mesh, points);
406         get_topology(mesh, poly_verts, loop_counts, smooth_normal);
407
408         if (m_first_frame && m_settings.export_face_sets) {
409                 writeFaceSets(mesh, m_mesh_schema);
410         }
411
412         m_mesh_sample = OPolyMeshSchema::Sample(V3fArraySample(points),
413                                                 Int32ArraySample(poly_verts),
414                                                 Int32ArraySample(loop_counts));
415
416         UVSample sample;
417         if (m_first_frame && m_settings.export_uvs) {
418                 const char *name = get_uv_sample(sample, m_custom_data_config, &mesh->ldata);
419
420                 if (!sample.indices.empty() && !sample.uvs.empty()) {
421                         OV2fGeomParam::Sample uv_sample;
422                         uv_sample.setVals(V2fArraySample(sample.uvs));
423                         uv_sample.setIndices(UInt32ArraySample(sample.indices));
424                         uv_sample.setScope(kFacevaryingScope);
425
426                         m_mesh_schema.setUVSourceName(name);
427                         m_mesh_sample.setUVs(uv_sample);
428                 }
429
430                 write_custom_data(m_mesh_schema.getArbGeomParams(), m_custom_data_config, &mesh->ldata, CD_MLOOPUV);
431         }
432
433         if (m_settings.export_normals) {
434                 if (smooth_normal) {
435                         get_loop_normals(mesh, normals);
436                 }
437                 else {
438                         get_vertex_normals(mesh, normals);
439                 }
440
441                 ON3fGeomParam::Sample normals_sample;
442                 if (!normals.empty()) {
443                         normals_sample.setScope((smooth_normal) ? kFacevaryingScope : kVertexScope);
444                         normals_sample.setVals(V3fArraySample(normals));
445                 }
446
447                 m_mesh_sample.setNormals(normals_sample);
448         }
449
450         if (m_is_liquid) {
451                 std::vector<Imath::V3f> velocities;
452                 getVelocities(mesh, velocities);
453
454                 m_mesh_sample.setVelocities(V3fArraySample(velocities));
455         }
456
457         m_mesh_sample.setSelfBounds(bounds());
458
459         m_mesh_schema.set(m_mesh_sample);
460
461         writeArbGeoParams(mesh);
462 }
463
464 void AbcGenericMeshWriter::writeSubD(struct Mesh *mesh)
465 {
466         std::vector<float> crease_sharpness;
467         std::vector<Imath::V3f> points;
468         std::vector<int32_t> poly_verts, loop_counts;
469         std::vector<int32_t> crease_indices, crease_lengths;
470
471         bool smooth_normal = false;
472
473         get_vertices(mesh, points);
474         get_topology(mesh, poly_verts, loop_counts, smooth_normal);
475         get_creases(mesh, crease_indices, crease_lengths, crease_sharpness);
476
477         if (m_first_frame && m_settings.export_face_sets) {
478                 writeFaceSets(mesh, m_subdiv_schema);
479         }
480
481         m_subdiv_sample = OSubDSchema::Sample(V3fArraySample(points),
482                                               Int32ArraySample(poly_verts),
483                                               Int32ArraySample(loop_counts));
484
485         UVSample sample;
486         if (m_first_frame && m_settings.export_uvs) {
487                 const char *name = get_uv_sample(sample, m_custom_data_config, &mesh->ldata);
488
489                 if (!sample.indices.empty() && !sample.uvs.empty()) {
490                         OV2fGeomParam::Sample uv_sample;
491                         uv_sample.setVals(V2fArraySample(sample.uvs));
492                         uv_sample.setIndices(UInt32ArraySample(sample.indices));
493                         uv_sample.setScope(kFacevaryingScope);
494
495                         m_subdiv_schema.setUVSourceName(name);
496                         m_subdiv_sample.setUVs(uv_sample);
497                 }
498
499                 write_custom_data(m_subdiv_schema.getArbGeomParams(), m_custom_data_config, &mesh->ldata, CD_MLOOPUV);
500         }
501
502         if (!crease_indices.empty()) {
503                 m_subdiv_sample.setCreaseIndices(Int32ArraySample(crease_indices));
504                 m_subdiv_sample.setCreaseLengths(Int32ArraySample(crease_lengths));
505                 m_subdiv_sample.setCreaseSharpnesses(FloatArraySample(crease_sharpness));
506         }
507
508         m_subdiv_sample.setSelfBounds(bounds());
509         m_subdiv_schema.set(m_subdiv_sample);
510
511         writeArbGeoParams(mesh);
512 }
513
514 template <typename Schema>
515 void AbcGenericMeshWriter::writeFaceSets(struct Mesh *me, Schema &schema)
516 {
517         std::map< std::string, std::vector<int32_t>> geo_groups;
518         getGeoGroups(me, geo_groups);
519
520         std::map< std::string, std::vector<int32_t>>::iterator it;
521         for (it = geo_groups.begin(); it != geo_groups.end(); ++it) {
522                 OFaceSet face_set = schema.createFaceSet(it->first);
523                 OFaceSetSchema::Sample samp;
524                 samp.setFaces(Int32ArraySample(it->second));
525                 face_set.getSchema().set(samp);
526         }
527 }
528
529 Mesh *AbcGenericMeshWriter::getFinalMesh(bool &r_needsfree)
530 {
531         /* We don't want subdivided mesh data */
532         if (m_subsurf_mod) {
533                 m_subsurf_mod->mode |= eModifierMode_DisableTemporary;
534         }
535
536         r_needsfree = false;
537
538         Scene *scene = DEG_get_evaluated_scene(m_settings.depsgraph);
539         Object *ob_eval = DEG_get_evaluated_object(m_settings.depsgraph, m_object);
540         struct Mesh *mesh = getEvaluatedMesh(scene, ob_eval, r_needsfree);
541
542         if (m_subsurf_mod) {
543                 m_subsurf_mod->mode &= ~eModifierMode_DisableTemporary;
544         }
545
546         if (m_settings.triangulate) {
547                 const bool tag_only = false;
548                 const int quad_method = m_settings.quad_method;
549                 const int ngon_method = m_settings.ngon_method;
550
551                 struct BMeshCreateParams bmcp = {false};
552                 struct BMeshFromMeshParams bmfmp = {true, false, false, 0};
553                 BMesh *bm = BKE_mesh_to_bmesh_ex(mesh, &bmcp, &bmfmp);
554
555                 BM_mesh_triangulate(bm, quad_method, ngon_method, 4, tag_only, NULL, NULL, NULL);
556
557                 Mesh *result = BKE_mesh_from_bmesh_for_eval_nomain(bm, NULL);
558                 BM_mesh_free(bm);
559
560                 if (r_needsfree) {
561                         BKE_id_free(NULL, mesh);
562                 }
563
564                 mesh = result;
565                 r_needsfree = true;
566         }
567
568         m_custom_data_config.pack_uvs = m_settings.pack_uv;
569         m_custom_data_config.mpoly = mesh->mpoly;
570         m_custom_data_config.mloop = mesh->mloop;
571         m_custom_data_config.totpoly = mesh->totpoly;
572         m_custom_data_config.totloop = mesh->totloop;
573         m_custom_data_config.totvert = mesh->totvert;
574
575         return mesh;
576 }
577
578 void AbcGenericMeshWriter::writeArbGeoParams(struct Mesh *me)
579 {
580         if (m_is_liquid) {
581                 /* We don't need anything more for liquid meshes. */
582                 return;
583         }
584
585         if (m_first_frame && m_settings.export_vcols) {
586                 if (m_subdiv_schema.valid()) {
587                         write_custom_data(m_subdiv_schema.getArbGeomParams(), m_custom_data_config, &me->ldata, CD_MLOOPCOL);
588                 }
589                 else {
590                         write_custom_data(m_mesh_schema.getArbGeomParams(), m_custom_data_config, &me->ldata, CD_MLOOPCOL);
591                 }
592         }
593 }
594
595 void AbcGenericMeshWriter::getVelocities(struct Mesh *mesh, std::vector<Imath::V3f> &vels)
596 {
597         const int totverts = mesh->totvert;
598
599         vels.clear();
600         vels.resize(totverts);
601
602         ModifierData *md = get_liquid_sim_modifier(m_settings.scene, m_object);
603         FluidsimModifierData *fmd = reinterpret_cast<FluidsimModifierData *>(md);
604         FluidsimSettings *fss = fmd->fss;
605
606         if (fss->meshVelocities) {
607                 float *mesh_vels = reinterpret_cast<float *>(fss->meshVelocities);
608
609                 for (int i = 0; i < totverts; ++i) {
610                         copy_yup_from_zup(vels[i].getValue(), mesh_vels);
611                         mesh_vels += 3;
612                 }
613         }
614         else {
615                 std::fill(vels.begin(), vels.end(), Imath::V3f(0.0f));
616         }
617 }
618
619 void AbcGenericMeshWriter::getGeoGroups(
620         struct Mesh *mesh,
621         std::map<std::string, std::vector<int32_t>> &geo_groups)
622 {
623         const int num_poly = mesh->totpoly;
624         MPoly *polygons = mesh->mpoly;
625
626         for (int i = 0; i < num_poly; ++i) {
627                 MPoly &current_poly = polygons[i];
628                 short mnr = current_poly.mat_nr;
629
630                 Material *mat = give_current_material(m_object, mnr + 1);
631
632                 if (!mat) {
633                         continue;
634                 }
635
636                 std::string name = get_id_name(&mat->id);
637
638                 if (geo_groups.find(name) == geo_groups.end()) {
639                         std::vector<int32_t> faceArray;
640                         geo_groups[name] = faceArray;
641                 }
642
643                 geo_groups[name].push_back(i);
644         }
645
646         if (geo_groups.size() == 0) {
647                 Material *mat = give_current_material(m_object, 1);
648
649                 std::string name = (mat) ? get_id_name(&mat->id) : "default";
650
651                 std::vector<int32_t> faceArray;
652
653                 for (int i = 0, e = mesh->totface; i < e; ++i) {
654                         faceArray.push_back(i);
655                 }
656
657                 geo_groups[name] = faceArray;
658         }
659 }
660
661
662 AbcMeshWriter::AbcMeshWriter(Object *ob,
663                              AbcTransformWriter *parent,
664                              uint32_t time_sampling,
665                              ExportSettings &settings)
666     : AbcGenericMeshWriter(ob, parent, time_sampling, settings)
667 {}
668
669 AbcMeshWriter::~AbcMeshWriter()
670 {}
671
672 Mesh *AbcMeshWriter::getEvaluatedMesh(Scene *scene_eval, Object *ob_eval, bool &UNUSED(r_needsfree))
673 {
674         return mesh_get_eval_final(m_settings.depsgraph, scene_eval, ob_eval, &CD_MASK_MESH);
675 }
676
677
678 /* ************************************************************************** */
679
680 /* Some helpers for mesh generation */
681 namespace utils {
682
683 static void build_mat_map(const Main *bmain, std::map<std::string, Material *> &mat_map)
684 {
685         Material *material = static_cast<Material *>(bmain->materials.first);
686
687         for (; material; material = static_cast<Material *>(material->id.next)) {
688                 mat_map[material->id.name + 2] = material;
689         }
690 }
691
692 static void assign_materials(Main *bmain, Object *ob, const std::map<std::string, int> &mat_index_map)
693 {
694         bool can_assign = true;
695         std::map<std::string, int>::const_iterator it = mat_index_map.begin();
696
697         int matcount = 0;
698         for (; it != mat_index_map.end(); ++it, ++matcount) {
699                 if (!BKE_object_material_slot_add(bmain, ob)) {
700                         can_assign = false;
701                         break;
702                 }
703         }
704
705         /* TODO(kevin): use global map? */
706         std::map<std::string, Material *> mat_map;
707         build_mat_map(bmain, mat_map);
708
709         std::map<std::string, Material *>::iterator mat_iter;
710
711         if (can_assign) {
712                 it = mat_index_map.begin();
713
714                 for (; it != mat_index_map.end(); ++it) {
715                         std::string mat_name = it->first;
716                         mat_iter = mat_map.find(mat_name.c_str());
717
718                         Material *assigned_mat;
719
720                         if (mat_iter == mat_map.end()) {
721                                 assigned_mat = BKE_material_add(bmain, mat_name.c_str());
722                                 mat_map[mat_name] = assigned_mat;
723                         }
724                         else {
725                                 assigned_mat = mat_iter->second;
726                         }
727
728                         assign_material(bmain, ob, assigned_mat, it->second, BKE_MAT_ASSIGN_OBDATA);
729                 }
730         }
731 }
732
733 }  /* namespace utils */
734
735 /* ************************************************************************** */
736
737 using Alembic::AbcGeom::UInt32ArraySamplePtr;
738 using Alembic::AbcGeom::V2fArraySamplePtr;
739
740 struct AbcMeshData {
741         Int32ArraySamplePtr face_indices;
742         Int32ArraySamplePtr face_counts;
743
744         P3fArraySamplePtr positions;
745         P3fArraySamplePtr ceil_positions;
746
747         N3fArraySamplePtr vertex_normals;
748         N3fArraySamplePtr face_normals;
749
750         V2fArraySamplePtr uvs;
751         UInt32ArraySamplePtr uvs_indices;
752 };
753
754 static void read_mverts_interp(MVert *mverts, const P3fArraySamplePtr &positions, const P3fArraySamplePtr &ceil_positions, const float weight)
755 {
756         float tmp[3];
757         for (int i = 0; i < positions->size(); ++i) {
758                 MVert &mvert = mverts[i];
759                 const Imath::V3f &floor_pos = (*positions)[i];
760                 const Imath::V3f &ceil_pos = (*ceil_positions)[i];
761
762                 interp_v3_v3v3(tmp, floor_pos.getValue(), ceil_pos.getValue(), weight);
763                 copy_zup_from_yup(mvert.co, tmp);
764
765                 mvert.bweight = 0;
766         }
767 }
768
769 static void read_mverts(CDStreamConfig &config, const AbcMeshData &mesh_data)
770 {
771         MVert *mverts = config.mvert;
772         const P3fArraySamplePtr &positions = mesh_data.positions;
773         const N3fArraySamplePtr &normals = mesh_data.vertex_normals;
774
775         if (   config.weight != 0.0f
776             && mesh_data.ceil_positions != NULL
777             && mesh_data.ceil_positions->size() == positions->size())
778         {
779                 read_mverts_interp(mverts, positions, mesh_data.ceil_positions, config.weight);
780                 return;
781         }
782
783         read_mverts(mverts, positions, normals);
784 }
785
786 void read_mverts(MVert *mverts, const P3fArraySamplePtr &positions, const N3fArraySamplePtr &normals)
787 {
788         for (int i = 0; i < positions->size(); ++i) {
789                 MVert &mvert = mverts[i];
790                 Imath::V3f pos_in = (*positions)[i];
791
792                 copy_zup_from_yup(mvert.co, pos_in.getValue());
793
794                 mvert.bweight = 0;
795
796                 if (normals) {
797                         Imath::V3f nor_in = (*normals)[i];
798
799                         short no[3];
800                         normal_float_to_short_v3(no, nor_in.getValue());
801
802                         copy_zup_from_yup(mvert.no, no);
803                 }
804         }
805 }
806
807 static void read_mpolys(CDStreamConfig &config, const AbcMeshData &mesh_data)
808 {
809         MPoly *mpolys = config.mpoly;
810         MLoop *mloops = config.mloop;
811         MLoopUV *mloopuvs = config.mloopuv;
812
813         const Int32ArraySamplePtr &face_indices = mesh_data.face_indices;
814         const Int32ArraySamplePtr &face_counts = mesh_data.face_counts;
815         const V2fArraySamplePtr &uvs = mesh_data.uvs;
816         const UInt32ArraySamplePtr &uvs_indices = mesh_data.uvs_indices;
817         const N3fArraySamplePtr &normals = mesh_data.face_normals;
818
819         const bool do_uvs = (mloopuvs && uvs && uvs_indices) && (uvs_indices->size() == face_indices->size());
820         unsigned int loop_index = 0;
821         unsigned int rev_loop_index = 0;
822         unsigned int uv_index = 0;
823
824         for (int i = 0; i < face_counts->size(); ++i) {
825                 const int face_size = (*face_counts)[i];
826
827                 MPoly &poly = mpolys[i];
828                 poly.loopstart = loop_index;
829                 poly.totloop = face_size;
830
831                 if (normals != NULL) {
832                         poly.flag |= ME_SMOOTH;
833                 }
834
835                 /* NOTE: Alembic data is stored in the reverse order. */
836                 rev_loop_index = loop_index + (face_size - 1);
837
838                 for (int f = 0; f < face_size; ++f, ++loop_index, --rev_loop_index) {
839                         MLoop &loop = mloops[rev_loop_index];
840                         loop.v = (*face_indices)[loop_index];
841
842                         if (do_uvs) {
843                                 MLoopUV &loopuv = mloopuvs[rev_loop_index];
844
845                                 uv_index = (*uvs_indices)[loop_index];
846                                 loopuv.uv[0] = (*uvs)[uv_index][0];
847                                 loopuv.uv[1] = (*uvs)[uv_index][1];
848                         }
849                 }
850         }
851 }
852
853 ABC_INLINE void read_uvs_params(CDStreamConfig &config,
854                                 AbcMeshData &abc_data,
855                                 const IV2fGeomParam &uv,
856                                 const ISampleSelector &selector)
857 {
858         if (!uv.valid()) {
859                 return;
860         }
861
862         IV2fGeomParam::Sample uvsamp;
863         uv.getIndexed(uvsamp, selector);
864
865         abc_data.uvs = uvsamp.getVals();
866         abc_data.uvs_indices = uvsamp.getIndices();
867
868         if (abc_data.uvs_indices->size() == config.totloop) {
869                 std::string name = Alembic::Abc::GetSourceName(uv.getMetaData());
870
871                 /* According to the convention, primary UVs should have had their name
872                  * set using Alembic::Abc::SetSourceName, but you can't expect everyone
873                  * to follow it! :) */
874                 if (name.empty()) {
875                         name = uv.getName();
876                 }
877
878                 void *cd_ptr = config.add_customdata_cb(config.user_data, name.c_str(), CD_MLOOPUV);
879                 config.mloopuv = static_cast<MLoopUV *>(cd_ptr);
880         }
881 }
882
883 /* TODO(kevin): normals from Alembic files are not read in anymore, this is due
884  * to the fact that there are many issues that are not so easy to solve, mainly
885  * regarding the way normals are handled in Blender (MPoly.flag vs loop normals).
886  */
887 ABC_INLINE void read_normals_params(AbcMeshData &abc_data,
888                                     const IN3fGeomParam &normals,
889                                     const ISampleSelector &selector)
890 {
891         if (!normals.valid()) {
892                 return;
893         }
894
895         IN3fGeomParam::Sample normsamp = normals.getExpandedValue(selector);
896
897         if (normals.getScope() == kFacevaryingScope) {
898                 abc_data.face_normals = normsamp.getVals();
899         }
900         else if ((normals.getScope() == kVertexScope) || (normals.getScope() == kVaryingScope)) {
901                 abc_data.vertex_normals = N3fArraySamplePtr();
902         }
903 }
904
905 static bool check_smooth_poly_flag(Mesh *mesh)
906 {
907         MPoly *mpolys = mesh->mpoly;
908
909         for (int i = 0, e = mesh->totpoly; i < e; ++i) {
910                 MPoly &poly = mpolys[i];
911
912                 if ((poly.flag & ME_SMOOTH) != 0) {
913                         return true;
914                 }
915         }
916
917         return false;
918 }
919
920 static void set_smooth_poly_flag(Mesh *mesh)
921 {
922         MPoly *mpolys = mesh->mpoly;
923
924         for (int i = 0, e = mesh->totpoly; i < e; ++i) {
925                 MPoly &poly = mpolys[i];
926                 poly.flag |= ME_SMOOTH;
927         }
928 }
929
930 static void *add_customdata_cb(void *user_data, const char *name, int data_type)
931 {
932         Mesh *mesh = static_cast<Mesh *>(user_data);
933         CustomDataType cd_data_type = static_cast<CustomDataType>(data_type);
934         void *cd_ptr;
935         CustomData *loopdata;
936         int numloops;
937
938         /* unsupported custom data type -- don't do anything. */
939         if (!ELEM(cd_data_type, CD_MLOOPUV, CD_MLOOPCOL)) {
940                 return NULL;
941         }
942
943         loopdata = &mesh->ldata;
944         cd_ptr = CustomData_get_layer_named(loopdata, cd_data_type, name);
945         if (cd_ptr != NULL) {
946                 /* layer already exists, so just return it. */
947                 return cd_ptr;
948         }
949
950         /* create a new layer, taking care to construct the hopefully-soon-to-be-removed
951          * CD_MTEXPOLY layer too, with the same name. */
952         numloops = mesh->totloop;
953         cd_ptr = CustomData_add_layer_named(loopdata, cd_data_type, CD_DEFAULT,
954                                             NULL, numloops, name);
955         return cd_ptr;
956 }
957
958 static void get_weight_and_index(CDStreamConfig &config,
959                                  Alembic::AbcCoreAbstract::TimeSamplingPtr time_sampling,
960                                  size_t samples_number)
961 {
962         Alembic::AbcGeom::index_t i0, i1;
963
964         config.weight = get_weight_and_index(config.time,
965                                              time_sampling,
966                                              samples_number,
967                                              i0,
968                                              i1);
969
970         config.index = i0;
971         config.ceil_index = i1;
972 }
973
974 static void read_mesh_sample(const std::string & iobject_full_name,
975                              ImportSettings *settings,
976                              const IPolyMeshSchema &schema,
977                              const ISampleSelector &selector,
978                              CDStreamConfig &config,
979                              bool &do_normals)
980 {
981         const IPolyMeshSchema::Sample sample = schema.getValue(selector);
982
983         AbcMeshData abc_mesh_data;
984         abc_mesh_data.face_counts = sample.getFaceCounts();
985         abc_mesh_data.face_indices = sample.getFaceIndices();
986         abc_mesh_data.positions = sample.getPositions();
987
988         read_normals_params(abc_mesh_data, schema.getNormalsParam(), selector);
989
990         do_normals = (abc_mesh_data.face_normals != NULL);
991
992         get_weight_and_index(config, schema.getTimeSampling(), schema.getNumSamples());
993
994         if (config.weight != 0.0f) {
995                 Alembic::AbcGeom::IPolyMeshSchema::Sample ceil_sample;
996                 schema.get(ceil_sample, Alembic::Abc::ISampleSelector(config.ceil_index));
997                 abc_mesh_data.ceil_positions = ceil_sample.getPositions();
998         }
999
1000         if ((settings->read_flag & MOD_MESHSEQ_READ_UV) != 0) {
1001                 read_uvs_params(config, abc_mesh_data, schema.getUVsParam(), selector);
1002         }
1003
1004         if ((settings->read_flag & MOD_MESHSEQ_READ_VERT) != 0) {
1005                 read_mverts(config, abc_mesh_data);
1006         }
1007
1008         if ((settings->read_flag & MOD_MESHSEQ_READ_POLY) != 0) {
1009                 read_mpolys(config, abc_mesh_data);
1010         }
1011
1012         if ((settings->read_flag & (MOD_MESHSEQ_READ_UV | MOD_MESHSEQ_READ_COLOR)) != 0) {
1013                 read_custom_data(iobject_full_name,
1014                                  schema.getArbGeomParams(), config, selector);
1015         }
1016 }
1017
1018 CDStreamConfig get_config(Mesh *mesh)
1019 {
1020         CDStreamConfig config;
1021
1022         BLI_assert(mesh->mvert);
1023
1024         config.user_data = mesh;
1025         config.mvert = mesh->mvert;
1026         config.mloop = mesh->mloop;
1027         config.mpoly = mesh->mpoly;
1028         config.totloop = mesh->totloop;
1029         config.totpoly = mesh->totpoly;
1030         config.loopdata = &mesh->ldata;
1031         config.add_customdata_cb = add_customdata_cb;
1032
1033         return config;
1034 }
1035
1036 /* ************************************************************************** */
1037
1038 AbcMeshReader::AbcMeshReader(const IObject &object, ImportSettings &settings)
1039     : AbcObjectReader(object, settings)
1040 {
1041         m_settings->read_flag |= MOD_MESHSEQ_READ_ALL;
1042
1043         IPolyMesh ipoly_mesh(m_iobject, kWrapExisting);
1044         m_schema = ipoly_mesh.getSchema();
1045
1046         get_min_max_time(m_iobject, m_schema, m_min_time, m_max_time);
1047 }
1048
1049 bool AbcMeshReader::valid() const
1050 {
1051         return m_schema.valid();
1052 }
1053
1054 void AbcMeshReader::readObjectData(Main *bmain, const Alembic::Abc::ISampleSelector &sample_sel)
1055 {
1056         Mesh *mesh = BKE_mesh_add(bmain, m_data_name.c_str());
1057
1058         m_object = BKE_object_add_only_object(bmain, OB_MESH, m_object_name.c_str());
1059         m_object->data = mesh;
1060
1061         Mesh *read_mesh = this->read_mesh(mesh, sample_sel, MOD_MESHSEQ_READ_ALL, NULL);
1062         BKE_mesh_nomain_to_mesh(read_mesh, mesh, m_object, &CD_MASK_MESH, true);
1063
1064         if (m_settings->validate_meshes) {
1065                 BKE_mesh_validate(mesh, false, false);
1066         }
1067
1068         readFaceSetsSample(bmain, mesh, 0, sample_sel);
1069
1070         if (has_animations(m_schema, m_settings)) {
1071                 addCacheModifier();
1072         }
1073 }
1074
1075 bool AbcMeshReader::accepts_object_type(const Alembic::AbcCoreAbstract::ObjectHeader &alembic_header,
1076                                         const Object *const ob,
1077                                         const char **err_str) const
1078 {
1079         if (!Alembic::AbcGeom::IPolyMesh::matches(alembic_header)) {
1080                 *err_str = "Object type mismatch, Alembic object path pointed to PolyMesh when importing, but not any more.";
1081                 return false;
1082         }
1083
1084         if (ob->type != OB_MESH) {
1085                 *err_str = "Object type mismatch, Alembic object path points to PolyMesh.";
1086                 return false;
1087         }
1088
1089         return true;
1090 }
1091
1092 Mesh *AbcMeshReader::read_mesh(Mesh *existing_mesh,
1093                                const ISampleSelector &sample_sel,
1094                                int read_flag,
1095                                const char **err_str)
1096 {
1097         IPolyMeshSchema::Sample sample;
1098         try {
1099                 sample = m_schema.getValue(sample_sel);
1100         }
1101         catch(Alembic::Util::Exception &ex) {
1102                 *err_str = "Error reading mesh sample; more detail on the console";
1103                 printf("Alembic: error reading mesh sample for '%s/%s' at time %f: %s\n",
1104                        m_iobject.getFullName().c_str(),
1105                        m_schema.getName().c_str(),
1106                        sample_sel.getRequestedTime(),
1107                        ex.what());
1108                 return existing_mesh;
1109         }
1110
1111         const P3fArraySamplePtr &positions = sample.getPositions();
1112         const Alembic::Abc::Int32ArraySamplePtr &face_indices = sample.getFaceIndices();
1113         const Alembic::Abc::Int32ArraySamplePtr &face_counts = sample.getFaceCounts();
1114
1115         Mesh *new_mesh = NULL;
1116
1117         /* Only read point data when streaming meshes, unless we need to create new ones. */
1118         ImportSettings settings;
1119         settings.read_flag |= read_flag;
1120
1121         bool topology_changed =  positions->size() != existing_mesh->totvert ||
1122                                  face_counts->size() != existing_mesh->totpoly ||
1123                                  face_indices->size() != existing_mesh->totloop;
1124         if (topology_changed) {
1125                 new_mesh = BKE_mesh_new_nomain_from_template(existing_mesh,
1126                                                              positions->size(),
1127                                                              0,
1128                                                              0,
1129                                                              face_indices->size(),
1130                                                              face_counts->size());
1131
1132                 settings.read_flag |= MOD_MESHSEQ_READ_ALL;
1133         }
1134         else {
1135                 /* If the face count changed (e.g. by triangulation), only read points.
1136                  * This prevents crash from T49813.
1137                  * TODO(kevin): perhaps find a better way to do this? */
1138                 if (face_counts->size() != existing_mesh->totpoly ||
1139                     face_indices->size() != existing_mesh->totloop)
1140                 {
1141                         settings.read_flag = MOD_MESHSEQ_READ_VERT;
1142
1143                         if (err_str) {
1144                                 *err_str = "Topology has changed, perhaps by triangulating the"
1145                                            " mesh. Only vertices will be read!";
1146                         }
1147                 }
1148         }
1149
1150         CDStreamConfig config = get_config(new_mesh ? new_mesh : existing_mesh);
1151         config.time = sample_sel.getRequestedTime();
1152
1153         bool do_normals = false;
1154         read_mesh_sample(m_iobject.getFullName(),
1155                          &settings, m_schema, sample_sel, config, do_normals);
1156
1157         if (new_mesh) {
1158                 /* Check if we had ME_SMOOTH flag set to restore it. */
1159                 if (!do_normals && check_smooth_poly_flag(existing_mesh)) {
1160                         set_smooth_poly_flag(new_mesh);
1161                 }
1162
1163                 BKE_mesh_calc_normals(new_mesh);
1164                 BKE_mesh_calc_edges(new_mesh, false, false);
1165
1166                 /* Here we assume that the number of materials doesn't change, i.e. that
1167                  * the material slots that were created when the object was loaded from
1168                  * Alembic are still valid now. */
1169                 size_t num_polys = new_mesh->totpoly;
1170                 if (num_polys > 0) {
1171                         std::map<std::string, int> mat_map;
1172                         assign_facesets_to_mpoly(sample_sel, 0, new_mesh->mpoly, num_polys, mat_map);
1173                 }
1174
1175                 return new_mesh;
1176         }
1177
1178         if (do_normals) {
1179                 BKE_mesh_calc_normals(existing_mesh);
1180         }
1181
1182         return existing_mesh;
1183 }
1184
1185 void AbcMeshReader::assign_facesets_to_mpoly(
1186         const ISampleSelector &sample_sel,
1187         size_t poly_start,
1188         MPoly *mpoly, int totpoly,
1189         std::map<std::string, int> & r_mat_map)
1190 {
1191         std::vector<std::string> face_sets;
1192         m_schema.getFaceSetNames(face_sets);
1193
1194         if (face_sets.empty()) {
1195                 return;
1196         }
1197
1198         int current_mat = 0;
1199
1200         for (int i = 0; i < face_sets.size(); ++i) {
1201                 const std::string &grp_name = face_sets[i];
1202
1203                 if (r_mat_map.find(grp_name) == r_mat_map.end()) {
1204                         r_mat_map[grp_name] = 1 + current_mat++;
1205                 }
1206
1207                 const int assigned_mat = r_mat_map[grp_name];
1208
1209                 const IFaceSet faceset = m_schema.getFaceSet(grp_name);
1210
1211                 if (!faceset.valid()) {
1212                         std::cerr << " Face set " << grp_name << " invalid for " << m_object_name << "\n";
1213                         continue;
1214                 }
1215
1216                 const IFaceSetSchema face_schem = faceset.getSchema();
1217                 const IFaceSetSchema::Sample face_sample = face_schem.getValue(sample_sel);
1218                 const Int32ArraySamplePtr group_faces = face_sample.getFaces();
1219                 const size_t num_group_faces = group_faces->size();
1220
1221                 for (size_t l = 0; l < num_group_faces; l++) {
1222                         size_t pos = (*group_faces)[l] + poly_start;
1223
1224                         if (pos >= totpoly) {
1225                                 std::cerr << "Faceset overflow on " << faceset.getName() << '\n';
1226                                 break;
1227                         }
1228
1229                         MPoly &poly = mpoly[pos];
1230                         poly.mat_nr = assigned_mat - 1;
1231                 }
1232         }
1233
1234 }
1235
1236 void AbcMeshReader::readFaceSetsSample(Main *bmain, Mesh *mesh, size_t poly_start,
1237                                        const ISampleSelector &sample_sel)
1238 {
1239         std::map<std::string, int> mat_map;
1240         assign_facesets_to_mpoly(sample_sel,
1241                                  poly_start, mesh->mpoly, mesh->totpoly,
1242                                  mat_map);
1243         utils::assign_materials(bmain, m_object, mat_map);
1244 }
1245
1246 /* ************************************************************************** */
1247
1248 ABC_INLINE MEdge *find_edge(MEdge *edges, int totedge, int v1, int v2)
1249 {
1250         for (int i = 0, e = totedge; i < e; ++i) {
1251                 MEdge &edge = edges[i];
1252
1253                 if (edge.v1 == v1 && edge.v2 == v2) {
1254                         return &edge;
1255                 }
1256         }
1257
1258         return NULL;
1259 }
1260
1261 static void read_subd_sample(const std::string & iobject_full_name,
1262                              ImportSettings *settings,
1263                              const ISubDSchema &schema,
1264                              const ISampleSelector &selector,
1265                              CDStreamConfig &config)
1266 {
1267         const ISubDSchema::Sample sample = schema.getValue(selector);
1268
1269         AbcMeshData abc_mesh_data;
1270         abc_mesh_data.face_counts = sample.getFaceCounts();
1271         abc_mesh_data.face_indices = sample.getFaceIndices();
1272         abc_mesh_data.vertex_normals = N3fArraySamplePtr();
1273         abc_mesh_data.face_normals = N3fArraySamplePtr();
1274         abc_mesh_data.positions = sample.getPositions();
1275
1276         get_weight_and_index(config, schema.getTimeSampling(), schema.getNumSamples());
1277
1278         if (config.weight != 0.0f) {
1279                 Alembic::AbcGeom::ISubDSchema::Sample ceil_sample;
1280                 schema.get(ceil_sample, Alembic::Abc::ISampleSelector(config.ceil_index));
1281                 abc_mesh_data.ceil_positions = ceil_sample.getPositions();
1282         }
1283
1284         if ((settings->read_flag & MOD_MESHSEQ_READ_UV) != 0) {
1285                 read_uvs_params(config, abc_mesh_data, schema.getUVsParam(), selector);
1286         }
1287
1288         if ((settings->read_flag & MOD_MESHSEQ_READ_VERT) != 0) {
1289                 read_mverts(config, abc_mesh_data);
1290         }
1291
1292         if ((settings->read_flag & MOD_MESHSEQ_READ_POLY) != 0) {
1293                 read_mpolys(config, abc_mesh_data);
1294         }
1295
1296         if ((settings->read_flag & (MOD_MESHSEQ_READ_UV | MOD_MESHSEQ_READ_COLOR)) != 0) {
1297                 read_custom_data(iobject_full_name,
1298                                  schema.getArbGeomParams(), config, selector);
1299         }
1300 }
1301
1302 /* ************************************************************************** */
1303
1304 AbcSubDReader::AbcSubDReader(const IObject &object, ImportSettings &settings)
1305     : AbcObjectReader(object, settings)
1306 {
1307         m_settings->read_flag |= MOD_MESHSEQ_READ_ALL;
1308
1309         ISubD isubd_mesh(m_iobject, kWrapExisting);
1310         m_schema = isubd_mesh.getSchema();
1311
1312         get_min_max_time(m_iobject, m_schema, m_min_time, m_max_time);
1313 }
1314
1315 bool AbcSubDReader::valid() const
1316 {
1317         return m_schema.valid();
1318 }
1319
1320 bool AbcSubDReader::accepts_object_type(const Alembic::AbcCoreAbstract::ObjectHeader &alembic_header,
1321                                         const Object *const ob,
1322                                         const char **err_str) const
1323 {
1324         if (!Alembic::AbcGeom::ISubD::matches(alembic_header)) {
1325                 *err_str = "Object type mismatch, Alembic object path pointed to SubD when importing, but not any more.";
1326                 return false;
1327         }
1328
1329         if (ob->type != OB_MESH) {
1330                 *err_str = "Object type mismatch, Alembic object path points to SubD.";
1331                 return false;
1332         }
1333
1334         return true;
1335 }
1336
1337 void AbcSubDReader::readObjectData(Main *bmain, const Alembic::Abc::ISampleSelector &sample_sel)
1338 {
1339         Mesh *mesh = BKE_mesh_add(bmain, m_data_name.c_str());
1340
1341         m_object = BKE_object_add_only_object(bmain, OB_MESH, m_object_name.c_str());
1342         m_object->data = mesh;
1343
1344         Mesh *read_mesh = this->read_mesh(mesh, sample_sel, MOD_MESHSEQ_READ_ALL, NULL);
1345         BKE_mesh_nomain_to_mesh(read_mesh, mesh, m_object, &CD_MASK_MESH, true);
1346
1347         ISubDSchema::Sample sample;
1348         try {
1349                 sample = m_schema.getValue(sample_sel);
1350         }
1351         catch(Alembic::Util::Exception &ex) {
1352                 printf("Alembic: error reading mesh sample for '%s/%s' at time %f: %s\n",
1353                        m_iobject.getFullName().c_str(),
1354                        m_schema.getName().c_str(),
1355                        sample_sel.getRequestedTime(),
1356                        ex.what());
1357                 return;
1358         }
1359
1360         Int32ArraySamplePtr indices = sample.getCreaseIndices();
1361         Alembic::Abc::FloatArraySamplePtr sharpnesses = sample.getCreaseSharpnesses();
1362
1363         MEdge *edges = mesh->medge;
1364
1365         if (indices && sharpnesses) {
1366                 for (int i = 0, s = 0, e = indices->size(); i < e; i += 2, ++s) {
1367                         MEdge *edge = find_edge(edges, mesh->totedge, (*indices)[i], (*indices)[i + 1]);
1368
1369                         if (edge) {
1370                                 edge->crease = unit_float_to_uchar_clamp((*sharpnesses)[s]);
1371                         }
1372                 }
1373
1374                 mesh->cd_flag |= ME_CDFLAG_EDGE_CREASE;
1375         }
1376
1377         BKE_mesh_calc_normals(mesh);
1378         BKE_mesh_calc_edges(mesh, false, false);
1379
1380         if (m_settings->validate_meshes) {
1381                 BKE_mesh_validate(mesh, false, false);
1382         }
1383
1384         if (has_animations(m_schema, m_settings)) {
1385                 addCacheModifier();
1386         }
1387 }
1388
1389 Mesh *AbcSubDReader::read_mesh(Mesh *existing_mesh,
1390                                const ISampleSelector &sample_sel,
1391                                int read_flag,
1392                                const char **err_str)
1393 {
1394         ISubDSchema::Sample sample;
1395         try {
1396                 sample = m_schema.getValue(sample_sel);
1397         }
1398         catch(Alembic::Util::Exception &ex) {
1399                 *err_str = "Error reading mesh sample; more detail on the console";
1400                 printf("Alembic: error reading mesh sample for '%s/%s' at time %f: %s\n",
1401                        m_iobject.getFullName().c_str(),
1402                        m_schema.getName().c_str(),
1403                        sample_sel.getRequestedTime(),
1404                        ex.what());
1405                 return existing_mesh;
1406         }
1407
1408         const P3fArraySamplePtr &positions = sample.getPositions();
1409         const Alembic::Abc::Int32ArraySamplePtr &face_indices = sample.getFaceIndices();
1410         const Alembic::Abc::Int32ArraySamplePtr &face_counts = sample.getFaceCounts();
1411
1412         Mesh *new_mesh = NULL;
1413
1414         ImportSettings settings;
1415         settings.read_flag |= read_flag;
1416
1417         if (existing_mesh->totvert != positions->size()) {
1418                 new_mesh = BKE_mesh_new_nomain_from_template(existing_mesh,
1419                                                            positions->size(),
1420                                                            0,
1421                                                            0,
1422                                                            face_indices->size(),
1423                                                            face_counts->size());
1424
1425                 settings.read_flag |= MOD_MESHSEQ_READ_ALL;
1426         }
1427         else {
1428                 /* If the face count changed (e.g. by triangulation), only read points.
1429                  * This prevents crash from T49813.
1430                  * TODO(kevin): perhaps find a better way to do this? */
1431                 if (face_counts->size() != existing_mesh->totpoly ||
1432                     face_indices->size() != existing_mesh->totpoly)
1433                 {
1434                         settings.read_flag = MOD_MESHSEQ_READ_VERT;
1435
1436                         if (err_str) {
1437                                 *err_str = "Topology has changed, perhaps by triangulating the"
1438                                            " mesh. Only vertices will be read!";
1439                         }
1440                 }
1441         }
1442
1443         /* Only read point data when streaming meshes, unless we need to create new ones. */
1444         CDStreamConfig config = get_config(new_mesh ? new_mesh : existing_mesh);
1445         config.time = sample_sel.getRequestedTime();
1446         read_subd_sample(m_iobject.getFullName(),
1447                          &settings, m_schema, sample_sel, config);
1448
1449         if (new_mesh) {
1450                 /* Check if we had ME_SMOOTH flag set to restore it. */
1451                 if (check_smooth_poly_flag(existing_mesh)) {
1452                         set_smooth_poly_flag(new_mesh);
1453                 }
1454
1455                 BKE_mesh_calc_normals(new_mesh);
1456                 BKE_mesh_calc_edges(new_mesh, false, false);
1457
1458                 return new_mesh;
1459         }
1460
1461         return existing_mesh;
1462 }