Merge remote-tracking branch 'origin/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(Scene *scene,
290                              Object *ob,
291                              AbcTransformWriter *parent,
292                              uint32_t time_sampling,
293                              ExportSettings &settings)
294     : AbcObjectWriter(scene, ob, time_sampling, settings, parent)
295 {
296         m_is_animated = isAnimated();
297         m_subsurf_mod = NULL;
298         m_is_subd = false;
299
300         /* If the object is static, use the default static time sampling. */
301         if (!m_is_animated) {
302                 time_sampling = 0;
303         }
304
305         if (!m_settings.apply_subdiv) {
306                 m_subsurf_mod = get_subsurf_modifier(m_scene, m_object);
307                 m_is_subd = (m_subsurf_mod != NULL);
308         }
309
310         m_is_liquid = (get_liquid_sim_modifier(m_scene, m_object) != NULL);
311
312         while (parent->alembicXform().getChildHeader(m_name)) {
313                 m_name.append("_");
314         }
315
316         if (m_settings.use_subdiv_schema && m_is_subd) {
317                 OSubD subd(parent->alembicXform(), m_name, m_time_sampling);
318                 m_subdiv_schema = subd.getSchema();
319         }
320         else {
321                 OPolyMesh mesh(parent->alembicXform(), m_name, m_time_sampling);
322                 m_mesh_schema = mesh.getSchema();
323
324                 OCompoundProperty typeContainer = m_mesh_schema.getUserProperties();
325                 OBoolProperty type(typeContainer, "meshtype");
326                 type.set(m_is_subd);
327         }
328 }
329
330 AbcMeshWriter::~AbcMeshWriter()
331 {
332         if (m_subsurf_mod) {
333                 m_subsurf_mod->mode &= ~eModifierMode_DisableTemporary;
334         }
335 }
336
337 bool AbcMeshWriter::isAnimated() const
338 {
339         /* Check if object has shape keys. */
340         Mesh *me = static_cast<Mesh *>(m_object->data);
341
342         if (me->key) {
343                 return true;
344         }
345
346         /* Test modifiers. */
347         ModifierData *md = static_cast<ModifierData *>(m_object->modifiers.first);
348
349         while (md) {
350                 if (md->type != eModifierType_Subsurf) {
351                         return true;
352                 }
353
354                 md = md->next;
355         }
356
357         return false;
358 }
359
360 void AbcMeshWriter::do_write()
361 {
362         /* We have already stored a sample for this object. */
363         if (!m_first_frame && !m_is_animated)
364                 return;
365
366         DerivedMesh *dm = getFinalMesh();
367
368         try {
369                 if (m_settings.use_subdiv_schema && m_subdiv_schema.valid()) {
370                         writeSubD(dm);
371                 }
372                 else {
373                         writeMesh(dm);
374                 }
375
376                 freeMesh(dm);
377         }
378         catch (...) {
379                 freeMesh(dm);
380                 throw;
381         }
382 }
383
384 void AbcMeshWriter::writeMesh(DerivedMesh *dm)
385 {
386         std::vector<Imath::V3f> points, normals;
387         std::vector<int32_t> poly_verts, loop_counts;
388
389         bool smooth_normal = false;
390
391         get_vertices(dm, points);
392         get_topology(dm, poly_verts, loop_counts, smooth_normal);
393
394         if (m_first_frame && m_settings.export_face_sets) {
395                 writeFaceSets(dm, m_mesh_schema);
396         }
397
398         m_mesh_sample = OPolyMeshSchema::Sample(V3fArraySample(points),
399                                                 Int32ArraySample(poly_verts),
400                                                 Int32ArraySample(loop_counts));
401
402         UVSample sample;
403         if (m_first_frame && m_settings.export_uvs) {
404                 const char *name = get_uv_sample(sample, m_custom_data_config, &dm->loopData);
405
406                 if (!sample.indices.empty() && !sample.uvs.empty()) {
407                         OV2fGeomParam::Sample uv_sample;
408                         uv_sample.setVals(V2fArraySample(sample.uvs));
409                         uv_sample.setIndices(UInt32ArraySample(sample.indices));
410                         uv_sample.setScope(kFacevaryingScope);
411
412                         m_mesh_schema.setUVSourceName(name);
413                         m_mesh_sample.setUVs(uv_sample);
414                 }
415
416                 write_custom_data(m_mesh_schema.getArbGeomParams(), m_custom_data_config, &dm->loopData, CD_MLOOPUV);
417         }
418
419         if (m_settings.export_normals) {
420                 if (smooth_normal) {
421                         get_loop_normals(dm, normals);
422                 }
423                 else {
424                         get_vertex_normals(dm, normals);
425                 }
426
427                 ON3fGeomParam::Sample normals_sample;
428                 if (!normals.empty()) {
429                         normals_sample.setScope((smooth_normal) ? kFacevaryingScope : kVertexScope);
430                         normals_sample.setVals(V3fArraySample(normals));
431                 }
432
433                 m_mesh_sample.setNormals(normals_sample);
434         }
435
436         if (m_is_liquid) {
437                 std::vector<Imath::V3f> velocities;
438                 getVelocities(dm, velocities);
439
440                 m_mesh_sample.setVelocities(V3fArraySample(velocities));
441         }
442
443         m_mesh_sample.setSelfBounds(bounds());
444
445         m_mesh_schema.set(m_mesh_sample);
446
447         writeArbGeoParams(dm);
448 }
449
450 void AbcMeshWriter::writeSubD(DerivedMesh *dm)
451 {
452         std::vector<float> crease_sharpness;
453         std::vector<Imath::V3f> points;
454         std::vector<int32_t> poly_verts, loop_counts;
455         std::vector<int32_t> crease_indices, crease_lengths;
456
457         bool smooth_normal = false;
458
459         get_vertices(dm, points);
460         get_topology(dm, poly_verts, loop_counts, smooth_normal);
461         get_creases(dm, crease_indices, crease_lengths, crease_sharpness);
462
463         if (m_first_frame && m_settings.export_face_sets) {
464                 writeFaceSets(dm, m_subdiv_schema);
465         }
466
467         m_subdiv_sample = OSubDSchema::Sample(V3fArraySample(points),
468                                               Int32ArraySample(poly_verts),
469                                               Int32ArraySample(loop_counts));
470
471         UVSample sample;
472         if (m_first_frame && m_settings.export_uvs) {
473                 const char *name = get_uv_sample(sample, m_custom_data_config, &dm->loopData);
474
475                 if (!sample.indices.empty() && !sample.uvs.empty()) {
476                         OV2fGeomParam::Sample uv_sample;
477                         uv_sample.setVals(V2fArraySample(sample.uvs));
478                         uv_sample.setIndices(UInt32ArraySample(sample.indices));
479                         uv_sample.setScope(kFacevaryingScope);
480
481                         m_subdiv_schema.setUVSourceName(name);
482                         m_subdiv_sample.setUVs(uv_sample);
483                 }
484
485                 write_custom_data(m_subdiv_schema.getArbGeomParams(), m_custom_data_config, &dm->loopData, CD_MLOOPUV);
486         }
487
488         if (!crease_indices.empty()) {
489                 m_subdiv_sample.setCreaseIndices(Int32ArraySample(crease_indices));
490                 m_subdiv_sample.setCreaseLengths(Int32ArraySample(crease_lengths));
491                 m_subdiv_sample.setCreaseSharpnesses(FloatArraySample(crease_sharpness));
492         }
493
494         m_subdiv_sample.setSelfBounds(bounds());
495         m_subdiv_schema.set(m_subdiv_sample);
496
497         writeArbGeoParams(dm);
498 }
499
500 template <typename Schema>
501 void AbcMeshWriter::writeFaceSets(DerivedMesh *dm, Schema &schema)
502 {
503         std::map< std::string, std::vector<int32_t> > geo_groups;
504         getGeoGroups(dm, geo_groups);
505
506         std::map< std::string, std::vector<int32_t>  >::iterator it;
507         for (it = geo_groups.begin(); it != geo_groups.end(); ++it) {
508                 OFaceSet face_set = schema.createFaceSet(it->first);
509                 OFaceSetSchema::Sample samp;
510                 samp.setFaces(Int32ArraySample(it->second));
511                 face_set.getSchema().set(samp);
512         }
513 }
514
515 DerivedMesh *AbcMeshWriter::getFinalMesh()
516 {
517         /* We don't want subdivided mesh data */
518         if (m_subsurf_mod) {
519                 m_subsurf_mod->mode |= eModifierMode_DisableTemporary;
520         }
521
522         DerivedMesh *dm = mesh_create_derived_render(m_scene, m_object, CD_MASK_MESH);
523
524         if (m_subsurf_mod) {
525                 m_subsurf_mod->mode &= ~eModifierMode_DisableTemporary;
526         }
527
528         if (m_settings.triangulate) {
529                 const bool tag_only = false;
530                 const int quad_method = m_settings.quad_method;
531                 const int ngon_method = m_settings.ngon_method;
532
533                 BMesh *bm = DM_to_bmesh(dm, true);
534
535                 BM_mesh_triangulate(bm, quad_method, ngon_method, tag_only, NULL, NULL, NULL);
536
537                 DerivedMesh *result = CDDM_from_bmesh(bm, false);
538                 BM_mesh_free(bm);
539
540                 freeMesh(dm);
541
542                 dm = result;
543         }
544
545         m_custom_data_config.pack_uvs = m_settings.pack_uv;
546         m_custom_data_config.mpoly = dm->getPolyArray(dm);
547         m_custom_data_config.mloop = dm->getLoopArray(dm);
548         m_custom_data_config.totpoly = dm->getNumPolys(dm);
549         m_custom_data_config.totloop = dm->getNumLoops(dm);
550         m_custom_data_config.totvert = dm->getNumVerts(dm);
551
552         return dm;
553 }
554
555 void AbcMeshWriter::freeMesh(DerivedMesh *dm)
556 {
557         dm->release(dm);
558 }
559
560 void AbcMeshWriter::writeArbGeoParams(DerivedMesh *dm)
561 {
562         if (m_is_liquid) {
563                 /* We don't need anything more for liquid meshes. */
564                 return;
565         }
566
567         if (m_first_frame && m_settings.export_vcols) {
568                 if (m_subdiv_schema.valid()) {
569                         write_custom_data(m_subdiv_schema.getArbGeomParams(), m_custom_data_config, &dm->loopData, CD_MLOOPCOL);
570                 }
571                 else {
572                         write_custom_data(m_mesh_schema.getArbGeomParams(), m_custom_data_config, &dm->loopData, CD_MLOOPCOL);
573                 }
574         }
575 }
576
577 void AbcMeshWriter::getVelocities(DerivedMesh *dm, std::vector<Imath::V3f> &vels)
578 {
579         const int totverts = dm->getNumVerts(dm);
580
581         vels.clear();
582         vels.resize(totverts);
583
584         ModifierData *md = get_liquid_sim_modifier(m_scene, m_object);
585         FluidsimModifierData *fmd = reinterpret_cast<FluidsimModifierData *>(md);
586         FluidsimSettings *fss = fmd->fss;
587
588         if (fss->meshVelocities) {
589                 float *mesh_vels = reinterpret_cast<float *>(fss->meshVelocities);
590
591                 for (int i = 0; i < totverts; ++i) {
592                         copy_yup_from_zup(vels[i].getValue(), mesh_vels);
593                         mesh_vels += 3;
594                 }
595         }
596         else {
597                 std::fill(vels.begin(), vels.end(), Imath::V3f(0.0f));
598         }
599 }
600
601 void AbcMeshWriter::getGeoGroups(
602         DerivedMesh *dm,
603         std::map<std::string, std::vector<int32_t> > &geo_groups)
604 {
605         const int num_poly = dm->getNumPolys(dm);
606         MPoly *polygons = dm->getPolyArray(dm);
607
608         for (int i = 0; i < num_poly; ++i) {
609                 MPoly &current_poly = polygons[i];
610                 short mnr = current_poly.mat_nr;
611
612                 Material *mat = give_current_material(m_object, mnr + 1);
613
614                 if (!mat) {
615                         continue;
616                 }
617
618                 std::string name = get_id_name(&mat->id);
619
620                 if (geo_groups.find(name) == geo_groups.end()) {
621                         std::vector<int32_t> faceArray;
622                         geo_groups[name] = faceArray;
623                 }
624
625                 geo_groups[name].push_back(i);
626         }
627
628         if (geo_groups.size() == 0) {
629                 Material *mat = give_current_material(m_object, 1);
630
631                 std::string name = (mat) ? get_id_name(&mat->id) : "default";
632
633                 std::vector<int32_t> faceArray;
634
635                 for (int i = 0, e = dm->getNumTessFaces(dm); i < e; ++i) {
636                         faceArray.push_back(i);
637                 }
638
639                 geo_groups[name] = faceArray;
640         }
641 }
642
643 /* ************************************************************************** */
644
645 /* Some helpers for mesh generation */
646 namespace utils {
647
648 static void build_mat_map(const Main *bmain, std::map<std::string, Material *> &mat_map)
649 {
650         Material *material = static_cast<Material *>(bmain->mat.first);
651
652         for (; material; material = static_cast<Material *>(material->id.next)) {
653                 mat_map[material->id.name + 2] = material;
654         }
655 }
656
657 static void assign_materials(Main *bmain, Object *ob, const std::map<std::string, int> &mat_index_map)
658 {
659         bool can_assign = true;
660         std::map<std::string, int>::const_iterator it = mat_index_map.begin();
661
662         int matcount = 0;
663         for (; it != mat_index_map.end(); ++it, ++matcount) {
664                 if (!BKE_object_material_slot_add(ob)) {
665                         can_assign = false;
666                         break;
667                 }
668         }
669
670         /* TODO(kevin): use global map? */
671         std::map<std::string, Material *> mat_map;
672         build_mat_map(bmain, mat_map);
673
674         std::map<std::string, Material *>::iterator mat_iter;
675
676         if (can_assign) {
677                 it = mat_index_map.begin();
678
679                 for (; it != mat_index_map.end(); ++it) {
680                         std::string mat_name = it->first;
681                         mat_iter = mat_map.find(mat_name.c_str());
682
683                         Material *assigned_name;
684
685                         if (mat_iter == mat_map.end()) {
686                                 assigned_name = BKE_material_add(bmain, mat_name.c_str());
687                                 mat_map[mat_name] = assigned_name;
688                         }
689                         else {
690                                 assigned_name = mat_iter->second;
691                         }
692
693                         assign_material(ob, assigned_name, it->second, BKE_MAT_ASSIGN_OBDATA);
694                 }
695         }
696 }
697
698 }  /* namespace utils */
699
700 /* ************************************************************************** */
701
702 using Alembic::AbcGeom::UInt32ArraySamplePtr;
703 using Alembic::AbcGeom::V2fArraySamplePtr;
704
705 struct AbcMeshData {
706         Int32ArraySamplePtr face_indices;
707         Int32ArraySamplePtr face_counts;
708
709         P3fArraySamplePtr positions;
710         P3fArraySamplePtr ceil_positions;
711
712         N3fArraySamplePtr vertex_normals;
713         N3fArraySamplePtr face_normals;
714
715         V2fArraySamplePtr uvs;
716         UInt32ArraySamplePtr uvs_indices;
717 };
718
719 static void read_mverts_interp(MVert *mverts, const P3fArraySamplePtr &positions, const P3fArraySamplePtr &ceil_positions, const float weight)
720 {
721         float tmp[3];
722         for (int i = 0; i < positions->size(); ++i) {
723                 MVert &mvert = mverts[i];
724                 const Imath::V3f &floor_pos = (*positions)[i];
725                 const Imath::V3f &ceil_pos = (*ceil_positions)[i];
726
727                 interp_v3_v3v3(tmp, floor_pos.getValue(), ceil_pos.getValue(), weight);
728                 copy_zup_from_yup(mvert.co, tmp);
729
730                 mvert.bweight = 0;
731         }
732 }
733
734 static void read_mverts(CDStreamConfig &config, const AbcMeshData &mesh_data)
735 {
736         MVert *mverts = config.mvert;
737         const P3fArraySamplePtr &positions = mesh_data.positions;
738         const N3fArraySamplePtr &normals = mesh_data.vertex_normals;
739
740         if (   config.weight != 0.0f
741             && mesh_data.ceil_positions != NULL
742             && mesh_data.ceil_positions->size() == positions->size())
743         {
744                 read_mverts_interp(mverts, positions, mesh_data.ceil_positions, config.weight);
745                 return;
746         }
747
748         read_mverts(mverts, positions, normals);
749 }
750
751 void read_mverts(MVert *mverts, const P3fArraySamplePtr &positions, const N3fArraySamplePtr &normals)
752 {
753         for (int i = 0; i < positions->size(); ++i) {
754                 MVert &mvert = mverts[i];
755                 Imath::V3f pos_in = (*positions)[i];
756
757                 copy_zup_from_yup(mvert.co, pos_in.getValue());
758
759                 mvert.bweight = 0;
760
761                 if (normals) {
762                         Imath::V3f nor_in = (*normals)[i];
763
764                         short no[3];
765                         normal_float_to_short_v3(no, nor_in.getValue());
766
767                         copy_zup_from_yup(mvert.no, no);
768                 }
769         }
770 }
771
772 static void read_mpolys(CDStreamConfig &config, const AbcMeshData &mesh_data)
773 {
774         MPoly *mpolys = config.mpoly;
775         MLoop *mloops = config.mloop;
776         MLoopUV *mloopuvs = config.mloopuv;
777
778         const Int32ArraySamplePtr &face_indices = mesh_data.face_indices;
779         const Int32ArraySamplePtr &face_counts = mesh_data.face_counts;
780         const V2fArraySamplePtr &uvs = mesh_data.uvs;
781         const UInt32ArraySamplePtr &uvs_indices = mesh_data.uvs_indices;
782         const N3fArraySamplePtr &normals = mesh_data.face_normals;
783
784         const bool do_uvs = (mloopuvs && uvs && uvs_indices) && (uvs_indices->size() == face_indices->size());
785         unsigned int loop_index = 0;
786         unsigned int rev_loop_index = 0;
787         unsigned int uv_index = 0;
788
789         for (int i = 0; i < face_counts->size(); ++i) {
790                 const int face_size = (*face_counts)[i];
791
792                 MPoly &poly = mpolys[i];
793                 poly.loopstart = loop_index;
794                 poly.totloop = face_size;
795
796                 if (normals != NULL) {
797                         poly.flag |= ME_SMOOTH;
798                 }
799
800                 /* NOTE: Alembic data is stored in the reverse order. */
801                 rev_loop_index = loop_index + (face_size - 1);
802
803                 for (int f = 0; f < face_size; ++f, ++loop_index, --rev_loop_index) {
804                         MLoop &loop = mloops[rev_loop_index];
805                         loop.v = (*face_indices)[loop_index];
806
807                         if (do_uvs) {
808                                 MLoopUV &loopuv = mloopuvs[rev_loop_index];
809
810                                 uv_index = (*uvs_indices)[loop_index];
811                                 loopuv.uv[0] = (*uvs)[uv_index][0];
812                                 loopuv.uv[1] = (*uvs)[uv_index][1];
813                         }
814                 }
815         }
816 }
817
818 ABC_INLINE void read_uvs_params(CDStreamConfig &config,
819                                 AbcMeshData &abc_data,
820                                 const IV2fGeomParam &uv,
821                                 const ISampleSelector &selector)
822 {
823         if (!uv.valid()) {
824                 return;
825         }
826
827         IV2fGeomParam::Sample uvsamp;
828         uv.getIndexed(uvsamp, selector);
829
830         abc_data.uvs = uvsamp.getVals();
831         abc_data.uvs_indices = uvsamp.getIndices();
832
833         if (abc_data.uvs_indices->size() == config.totloop) {
834                 std::string name = Alembic::Abc::GetSourceName(uv.getMetaData());
835
836                 /* According to the convention, primary UVs should have had their name
837                  * set using Alembic::Abc::SetSourceName, but you can't expect everyone
838                  * to follow it! :) */
839                 if (name.empty()) {
840                         name = uv.getName();
841                 }
842
843                 void *cd_ptr = config.add_customdata_cb(config.user_data, name.c_str(), CD_MLOOPUV);
844                 config.mloopuv = static_cast<MLoopUV *>(cd_ptr);
845         }
846 }
847
848 /* TODO(kevin): normals from Alembic files are not read in anymore, this is due
849  * to the fact that there are many issues that are not so easy to solve, mainly
850  * regarding the way normals are handled in Blender (MPoly.flag vs loop normals).
851  */
852 ABC_INLINE void read_normals_params(AbcMeshData &abc_data,
853                                     const IN3fGeomParam &normals,
854                                     const ISampleSelector &selector)
855 {
856         if (!normals.valid()) {
857                 return;
858         }
859
860         IN3fGeomParam::Sample normsamp = normals.getExpandedValue(selector);
861
862         if (normals.getScope() == kFacevaryingScope) {
863                 abc_data.face_normals = normsamp.getVals();
864         }
865         else if ((normals.getScope() == kVertexScope) || (normals.getScope() == kVaryingScope)) {
866                 abc_data.vertex_normals = N3fArraySamplePtr();
867         }
868 }
869
870 static bool check_smooth_poly_flag(DerivedMesh *dm)
871 {
872         MPoly *mpolys = dm->getPolyArray(dm);
873
874         for (int i = 0, e = dm->getNumPolys(dm); i < e; ++i) {
875                 MPoly &poly = mpolys[i];
876
877                 if ((poly.flag & ME_SMOOTH) != 0) {
878                         return true;
879                 }
880         }
881
882         return false;
883 }
884
885 static void set_smooth_poly_flag(DerivedMesh *dm)
886 {
887         MPoly *mpolys = dm->getPolyArray(dm);
888
889         for (int i = 0, e = dm->getNumPolys(dm); i < e; ++i) {
890                 MPoly &poly = mpolys[i];
891                 poly.flag |= ME_SMOOTH;
892         }
893 }
894
895 static void *add_customdata_cb(void *user_data, const char *name, int data_type)
896 {
897         DerivedMesh *dm = static_cast<DerivedMesh *>(user_data);
898         CustomDataType cd_data_type = static_cast<CustomDataType>(data_type);
899         void *cd_ptr;
900         CustomData *loopdata;
901         int numloops;
902
903         /* unsupported custom data type -- don't do anything. */
904         if (!ELEM(cd_data_type, CD_MLOOPUV, CD_MLOOPCOL)) {
905                 return NULL;
906         }
907
908         loopdata = dm->getLoopDataLayout(dm);
909         cd_ptr = CustomData_get_layer_named(loopdata, cd_data_type, name);
910         if (cd_ptr != NULL) {
911                 /* layer already exists, so just return it. */
912                 return cd_ptr;
913         }
914
915         /* create a new layer, taking care to construct the hopefully-soon-to-be-removed
916          * CD_MTEXPOLY layer too, with the same name. */
917         numloops = dm->getNumLoops(dm);
918         cd_ptr = CustomData_add_layer_named(loopdata, cd_data_type, CD_DEFAULT,
919                                             NULL, numloops, name);
920         if (cd_data_type == CD_MLOOPUV) {
921                 CustomData_add_layer_named(dm->getPolyDataLayout(dm),
922                                            CD_MTEXPOLY, CD_DEFAULT,
923                                            NULL, numloops, name);
924         }
925
926         return cd_ptr;
927 }
928
929 static void get_weight_and_index(CDStreamConfig &config,
930                                  Alembic::AbcCoreAbstract::TimeSamplingPtr time_sampling,
931                                  size_t samples_number)
932 {
933         Alembic::AbcGeom::index_t i0, i1;
934
935         config.weight = get_weight_and_index(config.time,
936                                              time_sampling,
937                                              samples_number,
938                                              i0,
939                                              i1);
940
941         config.index = i0;
942         config.ceil_index = i1;
943 }
944
945 static void read_mesh_sample(ImportSettings *settings,
946                              const IPolyMeshSchema &schema,
947                              const ISampleSelector &selector,
948                              CDStreamConfig &config,
949                              bool &do_normals)
950 {
951         const IPolyMeshSchema::Sample sample = schema.getValue(selector);
952
953         AbcMeshData abc_mesh_data;
954         abc_mesh_data.face_counts = sample.getFaceCounts();
955         abc_mesh_data.face_indices = sample.getFaceIndices();
956         abc_mesh_data.positions = sample.getPositions();
957
958         read_normals_params(abc_mesh_data, schema.getNormalsParam(), selector);
959
960         do_normals = (abc_mesh_data.face_normals != NULL);
961
962         get_weight_and_index(config, schema.getTimeSampling(), schema.getNumSamples());
963
964         if (config.weight != 0.0f) {
965                 Alembic::AbcGeom::IPolyMeshSchema::Sample ceil_sample;
966                 schema.get(ceil_sample, Alembic::Abc::ISampleSelector(config.ceil_index));
967                 abc_mesh_data.ceil_positions = ceil_sample.getPositions();
968         }
969
970         if ((settings->read_flag & MOD_MESHSEQ_READ_UV) != 0) {
971                 read_uvs_params(config, abc_mesh_data, schema.getUVsParam(), selector);
972         }
973
974         if ((settings->read_flag & MOD_MESHSEQ_READ_VERT) != 0) {
975                 read_mverts(config, abc_mesh_data);
976         }
977
978         if ((settings->read_flag & MOD_MESHSEQ_READ_POLY) != 0) {
979                 read_mpolys(config, abc_mesh_data);
980         }
981
982         if ((settings->read_flag & (MOD_MESHSEQ_READ_UV | MOD_MESHSEQ_READ_COLOR)) != 0) {
983                 read_custom_data(schema.getArbGeomParams(), config, selector);
984         }
985
986         /* TODO: face sets */
987 }
988
989 CDStreamConfig get_config(DerivedMesh *dm)
990 {
991         CDStreamConfig config;
992
993         config.user_data = dm;
994         config.mvert = dm->getVertArray(dm);
995         config.mloop = dm->getLoopArray(dm);
996         config.mpoly = dm->getPolyArray(dm);
997         config.totloop = dm->getNumLoops(dm);
998         config.totpoly = dm->getNumPolys(dm);
999         config.loopdata = dm->getLoopDataLayout(dm);
1000         config.add_customdata_cb = add_customdata_cb;
1001
1002         return config;
1003 }
1004
1005 /* ************************************************************************** */
1006
1007 AbcMeshReader::AbcMeshReader(const IObject &object, ImportSettings &settings)
1008     : AbcObjectReader(object, settings)
1009 {
1010         m_settings->read_flag |= MOD_MESHSEQ_READ_ALL;
1011
1012         IPolyMesh ipoly_mesh(m_iobject, kWrapExisting);
1013         m_schema = ipoly_mesh.getSchema();
1014
1015         get_min_max_time(m_iobject, m_schema, m_min_time, m_max_time);
1016 }
1017
1018 bool AbcMeshReader::valid() const
1019 {
1020         return m_schema.valid();
1021 }
1022
1023 void AbcMeshReader::readObjectData(Main *bmain, const Alembic::Abc::ISampleSelector &sample_sel)
1024 {
1025         Mesh *mesh = BKE_mesh_add(bmain, m_data_name.c_str());
1026
1027         m_object = BKE_object_add_only_object(bmain, OB_MESH, m_object_name.c_str());
1028         m_object->data = mesh;
1029
1030         DerivedMesh *dm = CDDM_from_mesh(mesh);
1031         DerivedMesh *ndm = this->read_derivedmesh(dm, sample_sel, MOD_MESHSEQ_READ_ALL, NULL);
1032
1033         if (ndm != dm) {
1034                 dm->release(dm);
1035         }
1036
1037         DM_to_mesh(ndm, mesh, m_object, CD_MASK_MESH, true);
1038
1039         if (m_settings->validate_meshes) {
1040                 BKE_mesh_validate(mesh, false, false);
1041         }
1042
1043         readFaceSetsSample(bmain, mesh, 0, sample_sel);
1044
1045         if (has_animations(m_schema, m_settings)) {
1046                 addCacheModifier();
1047         }
1048 }
1049
1050 bool AbcMeshReader::accepts_object_type(const Alembic::AbcCoreAbstract::ObjectHeader &alembic_header,
1051                                         const Object *const ob,
1052                                         const char **err_str) const
1053 {
1054         if (!Alembic::AbcGeom::IPolyMesh::matches(alembic_header)) {
1055                 *err_str = "Object type mismatch, Alembic object path pointed to PolyMesh when importing, but not any more.";
1056                 return false;
1057         }
1058
1059         if (ob->type != OB_MESH) {
1060                 *err_str = "Object type mismatch, Alembic object path points to PolyMesh.";
1061                 return false;
1062         }
1063
1064         return true;
1065 }
1066
1067 DerivedMesh *AbcMeshReader::read_derivedmesh(DerivedMesh *dm,
1068                                              const ISampleSelector &sample_sel,
1069                                              int read_flag,
1070                                              const char **err_str)
1071 {
1072         const IPolyMeshSchema::Sample sample = m_schema.getValue(sample_sel);
1073
1074         const P3fArraySamplePtr &positions = sample.getPositions();
1075         const Alembic::Abc::Int32ArraySamplePtr &face_indices = sample.getFaceIndices();
1076         const Alembic::Abc::Int32ArraySamplePtr &face_counts = sample.getFaceCounts();
1077
1078         DerivedMesh *new_dm = NULL;
1079
1080         /* Only read point data when streaming meshes, unless we need to create new ones. */
1081         ImportSettings settings;
1082         settings.read_flag |= read_flag;
1083
1084         if (dm->getNumVerts(dm) != positions->size()) {
1085                 new_dm = CDDM_from_template(dm,
1086                                             positions->size(),
1087                                             0,
1088                                             0,
1089                                             face_indices->size(),
1090                                             face_counts->size());
1091
1092                 settings.read_flag |= MOD_MESHSEQ_READ_ALL;
1093         }
1094         else {
1095                 /* If the face count changed (e.g. by triangulation), only read points.
1096                  * This prevents crash from T49813.
1097                  * TODO(kevin): perhaps find a better way to do this? */
1098                 if (face_counts->size() != dm->getNumPolys(dm) ||
1099                     face_indices->size() != dm->getNumLoops(dm))
1100                 {
1101                         settings.read_flag = MOD_MESHSEQ_READ_VERT;
1102
1103                         if (err_str) {
1104                                 *err_str = "Topology has changed, perhaps by triangulating the"
1105                                            " mesh. Only vertices will be read!";
1106                         }
1107                 }
1108         }
1109
1110         CDStreamConfig config = get_config(new_dm ? new_dm : dm);
1111         config.time = sample_sel.getRequestedTime();
1112
1113         bool do_normals = false;
1114         read_mesh_sample(&settings, m_schema, sample_sel, config, do_normals);
1115
1116         if (new_dm) {
1117                 /* Check if we had ME_SMOOTH flag set to restore it. */
1118                 if (!do_normals && check_smooth_poly_flag(dm)) {
1119                         set_smooth_poly_flag(new_dm);
1120                 }
1121
1122                 CDDM_calc_normals(new_dm);
1123                 CDDM_calc_edges(new_dm);
1124
1125                 return new_dm;
1126         }
1127
1128         if (do_normals) {
1129                 CDDM_calc_normals(dm);
1130         }
1131
1132         return dm;
1133 }
1134
1135 void AbcMeshReader::readFaceSetsSample(Main *bmain, Mesh *mesh, size_t poly_start,
1136                                        const ISampleSelector &sample_sel)
1137 {
1138         std::vector<std::string> face_sets;
1139         m_schema.getFaceSetNames(face_sets);
1140
1141         if (face_sets.empty()) {
1142                 return;
1143         }
1144
1145         std::map<std::string, int> mat_map;
1146         int current_mat = 0;
1147
1148         for (int i = 0; i < face_sets.size(); ++i) {
1149                 const std::string &grp_name = face_sets[i];
1150
1151                 if (mat_map.find(grp_name) == mat_map.end()) {
1152                         mat_map[grp_name] = 1 + current_mat++;
1153                 }
1154
1155                 const int assigned_mat = mat_map[grp_name];
1156
1157                 const IFaceSet faceset = m_schema.getFaceSet(grp_name);
1158
1159                 if (!faceset.valid()) {
1160                         continue;
1161                 }
1162
1163                 const IFaceSetSchema face_schem = faceset.getSchema();
1164                 const IFaceSetSchema::Sample face_sample = face_schem.getValue(sample_sel);
1165                 const Int32ArraySamplePtr group_faces = face_sample.getFaces();
1166                 const size_t num_group_faces = group_faces->size();
1167
1168                 for (size_t l = 0; l < num_group_faces; l++) {
1169                         size_t pos = (*group_faces)[l] + poly_start;
1170
1171                         if (pos >= mesh->totpoly) {
1172                                 std::cerr << "Faceset overflow on " << faceset.getName() << '\n';
1173                                 break;
1174                         }
1175
1176                         MPoly &poly = mesh->mpoly[pos];
1177                         poly.mat_nr = assigned_mat - 1;
1178                 }
1179         }
1180
1181         utils::assign_materials(bmain, m_object, mat_map);
1182 }
1183
1184 /* ************************************************************************** */
1185
1186 ABC_INLINE MEdge *find_edge(MEdge *edges, int totedge, int v1, int v2)
1187 {
1188         for (int i = 0, e = totedge; i < e; ++i) {
1189                 MEdge &edge = edges[i];
1190
1191                 if (edge.v1 == v1 && edge.v2 == v2) {
1192                         return &edge;
1193                 }
1194         }
1195
1196         return NULL;
1197 }
1198
1199 static void read_subd_sample(ImportSettings *settings,
1200                              const ISubDSchema &schema,
1201                              const ISampleSelector &selector,
1202                              CDStreamConfig &config)
1203 {
1204         const ISubDSchema::Sample sample = schema.getValue(selector);
1205
1206         AbcMeshData abc_mesh_data;
1207         abc_mesh_data.face_counts = sample.getFaceCounts();
1208         abc_mesh_data.face_indices = sample.getFaceIndices();
1209         abc_mesh_data.vertex_normals = N3fArraySamplePtr();
1210         abc_mesh_data.face_normals = N3fArraySamplePtr();
1211         abc_mesh_data.positions = sample.getPositions();
1212
1213         get_weight_and_index(config, schema.getTimeSampling(), schema.getNumSamples());
1214
1215         if (config.weight != 0.0f) {
1216                 Alembic::AbcGeom::ISubDSchema::Sample ceil_sample;
1217                 schema.get(ceil_sample, Alembic::Abc::ISampleSelector(config.ceil_index));
1218                 abc_mesh_data.ceil_positions = ceil_sample.getPositions();
1219         }
1220
1221         if ((settings->read_flag & MOD_MESHSEQ_READ_UV) != 0) {
1222                 read_uvs_params(config, abc_mesh_data, schema.getUVsParam(), selector);
1223         }
1224
1225         if ((settings->read_flag & MOD_MESHSEQ_READ_VERT) != 0) {
1226                 read_mverts(config, abc_mesh_data);
1227         }
1228
1229         if ((settings->read_flag & MOD_MESHSEQ_READ_POLY) != 0) {
1230                 read_mpolys(config, abc_mesh_data);
1231         }
1232
1233         if ((settings->read_flag & (MOD_MESHSEQ_READ_UV | MOD_MESHSEQ_READ_COLOR)) != 0) {
1234                 read_custom_data(schema.getArbGeomParams(), config, selector);
1235         }
1236
1237         /* TODO: face sets */
1238 }
1239
1240 /* ************************************************************************** */
1241
1242 AbcSubDReader::AbcSubDReader(const IObject &object, ImportSettings &settings)
1243     : AbcObjectReader(object, settings)
1244 {
1245         m_settings->read_flag |= MOD_MESHSEQ_READ_ALL;
1246
1247         ISubD isubd_mesh(m_iobject, kWrapExisting);
1248         m_schema = isubd_mesh.getSchema();
1249
1250         get_min_max_time(m_iobject, m_schema, m_min_time, m_max_time);
1251 }
1252
1253 bool AbcSubDReader::valid() const
1254 {
1255         return m_schema.valid();
1256 }
1257
1258 bool AbcSubDReader::accepts_object_type(const Alembic::AbcCoreAbstract::ObjectHeader &alembic_header,
1259                                         const Object *const ob,
1260                                         const char **err_str) const
1261 {
1262         if (!Alembic::AbcGeom::ISubD::matches(alembic_header)) {
1263                 *err_str = "Object type mismatch, Alembic object path pointed to SubD when importing, but not any more.";
1264                 return false;
1265         }
1266
1267         if (ob->type != OB_MESH) {
1268                 *err_str = "Object type mismatch, Alembic object path points to SubD.";
1269                 return false;
1270         }
1271
1272         return true;
1273 }
1274
1275 void AbcSubDReader::readObjectData(Main *bmain, const Alembic::Abc::ISampleSelector &sample_sel)
1276 {
1277         Mesh *mesh = BKE_mesh_add(bmain, m_data_name.c_str());
1278
1279         m_object = BKE_object_add_only_object(bmain, OB_MESH, m_object_name.c_str());
1280         m_object->data = mesh;
1281
1282         DerivedMesh *dm = CDDM_from_mesh(mesh);
1283         DerivedMesh *ndm = this->read_derivedmesh(dm, sample_sel, MOD_MESHSEQ_READ_ALL, NULL);
1284
1285         if (ndm != dm) {
1286                 dm->release(dm);
1287         }
1288
1289         DM_to_mesh(ndm, mesh, m_object, CD_MASK_MESH, true);
1290
1291         const ISubDSchema::Sample sample = m_schema.getValue(sample_sel);
1292         Int32ArraySamplePtr indices = sample.getCreaseIndices();
1293         Alembic::Abc::FloatArraySamplePtr sharpnesses = sample.getCreaseSharpnesses();
1294
1295         MEdge *edges = mesh->medge;
1296
1297         if (indices && sharpnesses) {
1298                 for (int i = 0, s = 0, e = indices->size(); i < e; i += 2, ++s) {
1299                         MEdge *edge = find_edge(edges, mesh->totedge, (*indices)[i], (*indices)[i + 1]);
1300
1301                         if (edge) {
1302                                 edge->crease = FTOCHAR((*sharpnesses)[s]);
1303                         }
1304                 }
1305
1306                 mesh->cd_flag |= ME_CDFLAG_EDGE_CREASE;
1307         }
1308
1309         BKE_mesh_calc_normals(mesh);
1310         BKE_mesh_calc_edges(mesh, false, false);
1311
1312         if (m_settings->validate_meshes) {
1313                 BKE_mesh_validate(mesh, false, false);
1314         }
1315
1316         if (has_animations(m_schema, m_settings)) {
1317                 addCacheModifier();
1318         }
1319 }
1320
1321 DerivedMesh *AbcSubDReader::read_derivedmesh(DerivedMesh *dm,
1322                                              const ISampleSelector &sample_sel,
1323                                              int read_flag,
1324                                              const char **err_str)
1325 {
1326         const ISubDSchema::Sample sample = m_schema.getValue(sample_sel);
1327
1328         const P3fArraySamplePtr &positions = sample.getPositions();
1329         const Alembic::Abc::Int32ArraySamplePtr &face_indices = sample.getFaceIndices();
1330         const Alembic::Abc::Int32ArraySamplePtr &face_counts = sample.getFaceCounts();
1331
1332         DerivedMesh *new_dm = NULL;
1333
1334         ImportSettings settings;
1335         settings.read_flag |= read_flag;
1336
1337         if (dm->getNumVerts(dm) != positions->size()) {
1338                 new_dm = CDDM_from_template(dm,
1339                                             positions->size(),
1340                                             0,
1341                                             0,
1342                                             face_indices->size(),
1343                                             face_counts->size());
1344
1345                 settings.read_flag |= MOD_MESHSEQ_READ_ALL;
1346         }
1347         else {
1348                 /* If the face count changed (e.g. by triangulation), only read points.
1349                  * This prevents crash from T49813.
1350                  * TODO(kevin): perhaps find a better way to do this? */
1351                 if (face_counts->size() != dm->getNumPolys(dm) ||
1352                     face_indices->size() != dm->getNumLoops(dm))
1353                 {
1354                         settings.read_flag = MOD_MESHSEQ_READ_VERT;
1355
1356                         if (err_str) {
1357                                 *err_str = "Topology has changed, perhaps by triangulating the"
1358                                            " mesh. Only vertices will be read!";
1359                         }
1360                 }
1361         }
1362
1363         /* Only read point data when streaming meshes, unless we need to create new ones. */
1364         CDStreamConfig config = get_config(new_dm ? new_dm : dm);
1365         config.time = sample_sel.getRequestedTime();
1366         read_subd_sample(&settings, m_schema, sample_sel, config);
1367
1368         if (new_dm) {
1369                 /* Check if we had ME_SMOOTH flag set to restore it. */
1370                 if (check_smooth_poly_flag(dm)) {
1371                         set_smooth_poly_flag(new_dm);
1372                 }
1373
1374                 CDDM_calc_normals(new_dm);
1375                 CDDM_calc_edges(new_dm);
1376
1377                 return new_dm;
1378         }
1379
1380         return dm;
1381 }