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