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