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