Alembic: only export face sets when required by the user.
[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_zup_yup(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_material_indices(DerivedMesh *dm, std::vector<int32_t> &indices)
150 {
151         indices.clear();
152         indices.reserve(dm->getNumTessFaces(dm));
153
154         MPoly *mpolys = dm->getPolyArray(dm);
155
156         for (int i = 1, e = dm->getNumPolys(dm); i < e; ++i) {
157                 MPoly *mpoly = &mpolys[i];
158                 indices.push_back(mpoly->mat_nr);
159         }
160 }
161
162 static void get_creases(DerivedMesh *dm,
163                         std::vector<int32_t> &indices,
164                         std::vector<int32_t> &lengths,
165                         std::vector<float> &sharpnesses)
166 {
167         const float factor = 1.0f / 255.0f;
168
169         indices.clear();
170         lengths.clear();
171         sharpnesses.clear();
172
173         MEdge *edge = dm->getEdgeArray(dm);
174
175         for (int i = 0, e = dm->getNumEdges(dm); i < e; ++i) {
176                 const float sharpness = static_cast<float>(edge[i].crease) * factor;
177
178                 if (sharpness != 0.0f) {
179                         indices.push_back(edge[i].v1);
180                         indices.push_back(edge[i].v2);
181                         sharpnesses.push_back(sharpness);
182                 }
183         }
184
185         lengths.resize(sharpnesses.size(), 2);
186 }
187
188 static void get_vertex_normals(DerivedMesh *dm, std::vector<Imath::V3f> &normals)
189 {
190         normals.clear();
191         normals.resize(dm->getNumVerts(dm));
192
193         MVert *verts = dm->getVertArray(dm);
194         float no[3];
195
196         for (int i = 0, e = dm->getNumVerts(dm); i < e; ++i) {
197                 normal_short_to_float_v3(no, verts[i].no);
198                 copy_zup_yup(normals[i].getValue(), no);
199         }
200 }
201
202 static void get_loop_normals(DerivedMesh *dm, std::vector<Imath::V3f> &normals)
203 {
204         MPoly *mpoly = dm->getPolyArray(dm);
205         MPoly *mp = mpoly;
206
207         MLoop *mloop = dm->getLoopArray(dm);
208         MLoop *ml = mloop;
209
210         MVert *verts = dm->getVertArray(dm);
211
212         const float (*lnors)[3] = static_cast<float(*)[3]>(dm->getLoopDataArray(dm, CD_NORMAL));
213
214         normals.clear();
215         normals.resize(dm->getNumLoops(dm));
216
217         unsigned loop_index = 0;
218
219         /* NOTE: data needs to be written in the reverse order. */
220
221         if (lnors) {
222                 for (int i = 0, e = dm->getNumPolys(dm); i < e; ++i, ++mp) {
223                         ml = mloop + mp->loopstart + (mp->totloop - 1);
224
225                         for (int j = 0; j < mp->totloop; --ml, ++j, ++loop_index) {
226                                 const int index = ml->v;
227                                 copy_zup_yup(normals[loop_index].getValue(), lnors[index]);
228                         }
229                 }
230         }
231         else {
232                 float no[3];
233
234                 for (int i = 0, e = dm->getNumPolys(dm); i < e; ++i, ++mp) {
235                         ml = mloop + mp->loopstart + (mp->totloop - 1);
236
237                         /* Flat shaded, use common normal for all verts. */
238                         if ((mp->flag & ME_SMOOTH) == 0) {
239                                 BKE_mesh_calc_poly_normal(mp, ml - (mp->totloop - 1), verts, no);
240
241                                 for (int j = 0; j < mp->totloop; --ml, ++j, ++loop_index) {
242                                         copy_zup_yup(normals[loop_index].getValue(), no);
243                                 }
244                         }
245                         else {
246                                 /* Smooth shaded, use individual vert normals. */
247                                 for (int j = 0; j < mp->totloop; --ml, ++j, ++loop_index) {
248                                         normal_short_to_float_v3(no, verts[ml->v].no);
249                                         copy_zup_yup(normals[loop_index].getValue(), no);
250                                 }
251                         }
252                 }
253         }
254 }
255
256 /* *************** Modifiers *************** */
257
258 /* check if the mesh is a subsurf, ignoring disabled modifiers and
259  * displace if it's after subsurf. */
260 static ModifierData *get_subsurf_modifier(Scene *scene, Object *ob)
261 {
262         ModifierData *md = static_cast<ModifierData *>(ob->modifiers.last);
263
264         for (; md; md = md->prev) {
265                 if (!modifier_isEnabled(scene, md, eModifierMode_Render)) {
266                         continue;
267                 }
268
269                 if (md->type == eModifierType_Subsurf) {
270                         SubsurfModifierData *smd = reinterpret_cast<SubsurfModifierData*>(md);
271
272                         if (smd->subdivType == ME_CC_SUBSURF) {
273                                 return md;
274                         }
275                 }
276
277                 /* mesh is not a subsurf. break */
278                 if ((md->type != eModifierType_Displace) && (md->type != eModifierType_ParticleSystem)) {
279                         return NULL;
280                 }
281         }
282
283         return NULL;
284 }
285
286 static ModifierData *get_liquid_sim_modifier(Scene *scene, Object *ob)
287 {
288         ModifierData *md = modifiers_findByType(ob, eModifierType_Fluidsim);
289
290         if (md && (modifier_isEnabled(scene, md, eModifierMode_Render))) {
291                 FluidsimModifierData *fsmd = reinterpret_cast<FluidsimModifierData *>(md);
292
293                 if (fsmd->fss && fsmd->fss->type == OB_FLUIDSIM_DOMAIN) {
294                         return md;
295                 }
296         }
297
298         return NULL;
299 }
300
301 /* ************************************************************************** */
302
303 AbcMeshWriter::AbcMeshWriter(Scene *scene,
304                              Object *ob,
305                              AbcTransformWriter *parent,
306                              uint32_t time_sampling,
307                              ExportSettings &settings)
308     : AbcObjectWriter(scene, ob, time_sampling, settings, parent)
309 {
310         m_is_animated = isAnimated();
311         m_subsurf_mod = NULL;
312         m_is_subd = false;
313
314         /* If the object is static, use the default static time sampling. */
315         if (!m_is_animated) {
316                 time_sampling = 0;
317         }
318
319         if (!m_settings.apply_subdiv) {
320                 m_subsurf_mod = get_subsurf_modifier(m_scene, m_object);
321                 m_is_subd = (m_subsurf_mod != NULL);
322         }
323
324         m_is_liquid = (get_liquid_sim_modifier(m_scene, m_object) != NULL);
325
326         while (parent->alembicXform().getChildHeader(m_name)) {
327                 m_name.append("_");
328         }
329
330         if (m_settings.use_subdiv_schema && m_is_subd) {
331                 OSubD subd(parent->alembicXform(), m_name, m_time_sampling);
332                 m_subdiv_schema = subd.getSchema();
333         }
334         else {
335                 OPolyMesh mesh(parent->alembicXform(), m_name, m_time_sampling);
336                 m_mesh_schema = mesh.getSchema();
337
338                 OCompoundProperty typeContainer = m_mesh_schema.getUserProperties();
339                 OBoolProperty type(typeContainer, "meshtype");
340                 type.set(m_is_subd);
341         }
342 }
343
344 AbcMeshWriter::~AbcMeshWriter()
345 {
346         if (m_subsurf_mod) {
347                 m_subsurf_mod->mode &= ~eModifierMode_DisableTemporary;
348         }
349 }
350
351 bool AbcMeshWriter::isAnimated() const
352 {
353         /* Check if object has shape keys. */
354         Mesh *me = static_cast<Mesh *>(m_object->data);
355
356         if (me->key) {
357                 return true;
358         }
359
360         /* Test modifiers. */
361         ModifierData *md = static_cast<ModifierData *>(m_object->modifiers.first);
362
363         while (md) {
364                 if (md->type != eModifierType_Subsurf) {
365                         return true;
366                 }
367
368                 md = md->next;
369         }
370
371         return false;
372 }
373
374 void AbcMeshWriter::do_write()
375 {
376         /* We have already stored a sample for this object. */
377         if (!m_first_frame && !m_is_animated)
378                 return;
379
380         DerivedMesh *dm = getFinalMesh();
381
382         try {
383                 if (m_settings.use_subdiv_schema && m_subdiv_schema.valid()) {
384                         writeSubD(dm);
385                 }
386                 else {
387                         writeMesh(dm);
388                 }
389
390                 freeMesh(dm);
391         }
392         catch (...) {
393                 freeMesh(dm);
394                 throw;
395         }
396 }
397
398 void AbcMeshWriter::writeMesh(DerivedMesh *dm)
399 {
400         std::vector<Imath::V3f> points, normals;
401         std::vector<int32_t> poly_verts, loop_counts;
402
403         bool smooth_normal = false;
404
405         get_vertices(dm, points);
406         get_topology(dm, poly_verts, loop_counts, smooth_normal);
407
408         if (m_first_frame && m_settings.export_face_sets) {
409                 writeFaceSets(dm, m_mesh_schema);
410         }
411
412         m_mesh_sample = OPolyMeshSchema::Sample(V3fArraySample(points),
413                                                 Int32ArraySample(poly_verts),
414                                                 Int32ArraySample(loop_counts));
415
416         UVSample sample;
417         if (m_settings.export_uvs) {
418                 const char *name = get_uv_sample(sample, m_custom_data_config, &dm->loopData);
419
420                 if (!sample.indices.empty() && !sample.uvs.empty()) {
421                         OV2fGeomParam::Sample uv_sample;
422                         uv_sample.setVals(V2fArraySample(sample.uvs));
423                         uv_sample.setIndices(UInt32ArraySample(sample.indices));
424                         uv_sample.setScope(kFacevaryingScope);
425
426                         m_mesh_schema.setUVSourceName(name);
427                         m_mesh_sample.setUVs(uv_sample);
428                 }
429
430                 write_custom_data(m_mesh_schema.getArbGeomParams(), m_custom_data_config, &dm->loopData, CD_MLOOPUV);
431         }
432
433         if (m_settings.export_normals) {
434                 if (smooth_normal) {
435                         get_loop_normals(dm, normals);
436                 }
437                 else {
438                         get_vertex_normals(dm, normals);
439                 }
440
441                 ON3fGeomParam::Sample normals_sample;
442                 if (!normals.empty()) {
443                         normals_sample.setScope((smooth_normal) ? kFacevaryingScope : kVertexScope);
444                         normals_sample.setVals(V3fArraySample(normals));
445                 }
446
447                 m_mesh_sample.setNormals(normals_sample);
448         }
449
450         if (m_is_liquid) {
451                 std::vector<Imath::V3f> velocities;
452                 getVelocities(dm, velocities);
453
454                 m_mesh_sample.setVelocities(V3fArraySample(velocities));
455         }
456
457         m_mesh_sample.setSelfBounds(bounds());
458
459         m_mesh_schema.set(m_mesh_sample);
460
461         writeArbGeoParams(dm);
462 }
463
464 void AbcMeshWriter::writeSubD(DerivedMesh *dm)
465 {
466         std::vector<float> crease_sharpness;
467         std::vector<Imath::V3f> points;
468         std::vector<int32_t> poly_verts, loop_counts;
469         std::vector<int32_t> crease_indices, crease_lengths;
470
471         bool smooth_normal = false;
472
473         get_vertices(dm, points);
474         get_topology(dm, poly_verts, loop_counts, smooth_normal);
475         get_creases(dm, crease_indices, crease_lengths, crease_sharpness);
476
477         if (m_first_frame && m_settings.export_face_sets) {
478                 writeFaceSets(dm, m_subdiv_schema);
479         }
480
481         m_subdiv_sample = OSubDSchema::Sample(V3fArraySample(points),
482                                               Int32ArraySample(poly_verts),
483                                               Int32ArraySample(loop_counts));
484
485         UVSample sample;
486         if (m_settings.export_uvs) {
487                 const char *name = get_uv_sample(sample, m_custom_data_config, &dm->loopData);
488
489                 if (!sample.indices.empty() && !sample.uvs.empty()) {
490                         OV2fGeomParam::Sample uv_sample;
491                         uv_sample.setVals(V2fArraySample(sample.uvs));
492                         uv_sample.setIndices(UInt32ArraySample(sample.indices));
493                         uv_sample.setScope(kFacevaryingScope);
494
495                         m_subdiv_schema.setUVSourceName(name);
496                         m_subdiv_sample.setUVs(uv_sample);
497                 }
498
499                 write_custom_data(m_subdiv_schema.getArbGeomParams(), m_custom_data_config, &dm->loopData, CD_MLOOPUV);
500         }
501
502         if (!crease_indices.empty()) {
503                 m_subdiv_sample.setCreaseIndices(Int32ArraySample(crease_indices));
504                 m_subdiv_sample.setCreaseLengths(Int32ArraySample(crease_lengths));
505                 m_subdiv_sample.setCreaseSharpnesses(FloatArraySample(crease_sharpness));
506         }
507
508         m_subdiv_sample.setSelfBounds(bounds());
509         m_subdiv_schema.set(m_subdiv_sample);
510
511         writeArbGeoParams(dm);
512 }
513
514 template <typename Schema>
515 void AbcMeshWriter::writeFaceSets(DerivedMesh *dm, Schema &schema)
516 {
517         std::map< std::string, std::vector<int32_t> > geo_groups;
518         getGeoGroups(dm, geo_groups);
519
520         std::map< std::string, std::vector<int32_t>  >::iterator it;
521         for (it = geo_groups.begin(); it != geo_groups.end(); ++it) {
522                 OFaceSet face_set = schema.createFaceSet(it->first);
523                 OFaceSetSchema::Sample samp;
524                 samp.setFaces(Int32ArraySample(it->second));
525                 face_set.getSchema().set(samp);
526         }
527 }
528
529 DerivedMesh *AbcMeshWriter::getFinalMesh()
530 {
531         /* We don't want subdivided mesh data */
532         if (m_subsurf_mod) {
533                 m_subsurf_mod->mode |= eModifierMode_DisableTemporary;
534         }
535
536         DerivedMesh *dm = mesh_create_derived_render(m_scene, m_object, CD_MASK_MESH);
537
538         if (m_subsurf_mod) {
539                 m_subsurf_mod->mode &= ~eModifierMode_DisableTemporary;
540         }
541
542         if (m_settings.triangulate) {
543                 const bool tag_only = false;
544                 const int quad_method = m_settings.quad_method;
545                 const int ngon_method = m_settings.ngon_method;
546
547                 BMesh *bm = DM_to_bmesh(dm, true);
548
549                 BM_mesh_triangulate(bm, quad_method, ngon_method, tag_only, NULL, NULL, NULL);
550
551                 DerivedMesh *result = CDDM_from_bmesh(bm, false);
552                 BM_mesh_free(bm);
553
554                 freeMesh(dm);
555
556                 dm = result;
557         }
558
559         m_custom_data_config.pack_uvs = m_settings.pack_uv;
560         m_custom_data_config.mpoly = dm->getPolyArray(dm);
561         m_custom_data_config.mloop = dm->getLoopArray(dm);
562         m_custom_data_config.totpoly = dm->getNumPolys(dm);
563         m_custom_data_config.totloop = dm->getNumLoops(dm);
564         m_custom_data_config.totvert = dm->getNumVerts(dm);
565
566         return dm;
567 }
568
569 void AbcMeshWriter::freeMesh(DerivedMesh *dm)
570 {
571         dm->release(dm);
572 }
573
574 void AbcMeshWriter::writeArbGeoParams(DerivedMesh *dm)
575 {
576         if (m_is_liquid) {
577                 /* We don't need anything more for liquid meshes. */
578                 return;
579         }
580
581         if (m_settings.export_vcols) {
582                 if (m_subdiv_schema.valid()) {
583                         write_custom_data(m_subdiv_schema.getArbGeomParams(), m_custom_data_config, &dm->loopData, CD_MLOOPCOL);
584                 }
585                 else {
586                         write_custom_data(m_mesh_schema.getArbGeomParams(), m_custom_data_config, &dm->loopData, CD_MLOOPCOL);
587                 }
588         }
589 }
590
591 void AbcMeshWriter::getVelocities(DerivedMesh *dm, std::vector<Imath::V3f> &vels)
592 {
593         const int totverts = dm->getNumVerts(dm);
594
595         vels.clear();
596         vels.resize(totverts);
597
598         ModifierData *md = get_liquid_sim_modifier(m_scene, m_object);
599         FluidsimModifierData *fmd = reinterpret_cast<FluidsimModifierData *>(md);
600         FluidsimSettings *fss = fmd->fss;
601
602         if (fss->meshVelocities) {
603                 float *mesh_vels = reinterpret_cast<float *>(fss->meshVelocities);
604
605                 for (int i = 0; i < totverts; ++i) {
606                         copy_zup_yup(vels[i].getValue(), mesh_vels);
607                         mesh_vels += 3;
608                 }
609         }
610         else {
611                 std::fill(vels.begin(), vels.end(), Imath::V3f(0.0f));
612         }
613 }
614
615 void AbcMeshWriter::getGeoGroups(
616         DerivedMesh *dm,
617         std::map<std::string, std::vector<int32_t> > &geo_groups)
618 {
619         const int num_poly = dm->getNumPolys(dm);
620         MPoly *polygons = dm->getPolyArray(dm);
621
622         for (int i = 0; i < num_poly; ++i) {
623                 MPoly &current_poly = polygons[i];
624                 short mnr = current_poly.mat_nr;
625
626                 Material *mat = give_current_material(m_object, mnr + 1);
627
628                 if (!mat) {
629                         continue;
630                 }
631
632                 std::string name = get_id_name(&mat->id);
633
634                 if (geo_groups.find(name) == geo_groups.end()) {
635                         std::vector<int32_t> faceArray;
636                         geo_groups[name] = faceArray;
637                 }
638
639                 geo_groups[name].push_back(i);
640         }
641
642         if (geo_groups.size() == 0) {
643                 Material *mat = give_current_material(m_object, 1);
644
645                 std::string name = (mat) ? get_id_name(&mat->id) : "default";
646
647                 std::vector<int32_t> faceArray;
648
649                 for (int i = 0, e = dm->getNumTessFaces(dm); i < e; ++i) {
650                         faceArray.push_back(i);
651                 }
652
653                 geo_groups[name] = faceArray;
654         }
655 }
656
657 /* ************************************************************************** */
658
659 /* Some helpers for mesh generation */
660 namespace utils {
661
662 void mesh_add_verts(Mesh *mesh, size_t len)
663 {
664         if (len == 0) {
665                 return;
666         }
667
668         const int totvert = mesh->totvert + len;
669         CustomData vdata;
670         CustomData_copy(&mesh->vdata, &vdata, CD_MASK_MESH, CD_DEFAULT, totvert);
671         CustomData_copy_data(&mesh->vdata, &vdata, 0, 0, mesh->totvert);
672
673         if (!CustomData_has_layer(&vdata, CD_MVERT)) {
674                 CustomData_add_layer(&vdata, CD_MVERT, CD_CALLOC, NULL, totvert);
675         }
676
677         CustomData_free(&mesh->vdata, mesh->totvert);
678         mesh->vdata = vdata;
679         BKE_mesh_update_customdata_pointers(mesh, false);
680
681         mesh->totvert = totvert;
682 }
683
684 static void mesh_add_mloops(Mesh *mesh, size_t len)
685 {
686         if (len == 0) {
687                 return;
688         }
689
690         /* new face count */
691         const int totloops = mesh->totloop + len;
692
693         CustomData ldata;
694         CustomData_copy(&mesh->ldata, &ldata, CD_MASK_MESH, CD_DEFAULT, totloops);
695         CustomData_copy_data(&mesh->ldata, &ldata, 0, 0, mesh->totloop);
696
697         if (!CustomData_has_layer(&ldata, CD_MLOOP)) {
698                 CustomData_add_layer(&ldata, CD_MLOOP, CD_CALLOC, NULL, totloops);
699         }
700
701         CustomData_free(&mesh->ldata, mesh->totloop);
702         mesh->ldata = ldata;
703         BKE_mesh_update_customdata_pointers(mesh, false);
704
705         mesh->totloop = totloops;
706 }
707
708 static void mesh_add_mpolygons(Mesh *mesh, size_t len)
709 {
710         if (len == 0) {
711                 return;
712         }
713
714         const int totpolys = mesh->totpoly + len;
715
716         CustomData pdata;
717         CustomData_copy(&mesh->pdata, &pdata, CD_MASK_MESH, CD_DEFAULT, totpolys);
718         CustomData_copy_data(&mesh->pdata, &pdata, 0, 0, mesh->totpoly);
719
720         if (!CustomData_has_layer(&pdata, CD_MPOLY)) {
721                 CustomData_add_layer(&pdata, CD_MPOLY, CD_CALLOC, NULL, totpolys);
722         }
723
724         CustomData_free(&mesh->pdata, mesh->totpoly);
725         mesh->pdata = pdata;
726         BKE_mesh_update_customdata_pointers(mesh, false);
727
728         mesh->totpoly = totpolys;
729 }
730
731 static void build_mat_map(const Main *bmain, std::map<std::string, Material *> &mat_map)
732 {
733         Material *material = static_cast<Material *>(bmain->mat.first);
734
735         for (; material; material = static_cast<Material *>(material->id.next)) {
736                 mat_map[material->id.name + 2] = material;
737         }
738 }
739
740 static void assign_materials(Main *bmain, Object *ob, const std::map<std::string, int> &mat_index_map)
741 {
742         bool can_assign = true;
743         std::map<std::string, int>::const_iterator it = mat_index_map.begin();
744
745         int matcount = 0;
746         for (; it != mat_index_map.end(); ++it, ++matcount) {
747                 if (!BKE_object_material_slot_add(ob)) {
748                         can_assign = false;
749                         break;
750                 }
751         }
752
753         /* TODO(kevin): use global map? */
754         std::map<std::string, Material *> mat_map;
755         build_mat_map(bmain, mat_map);
756
757         std::map<std::string, Material *>::iterator mat_iter;
758
759         if (can_assign) {
760                 it = mat_index_map.begin();
761
762                 for (; it != mat_index_map.end(); ++it) {
763                         std::string mat_name = it->first;
764                         mat_iter = mat_map.find(mat_name.c_str());
765
766                         Material *assigned_name;
767
768                         if (mat_iter == mat_map.end()) {
769                                 assigned_name = BKE_material_add(bmain, mat_name.c_str());
770                                 mat_map[mat_name] = assigned_name;
771                         }
772                         else {
773                                 assigned_name = mat_iter->second;
774                         }
775
776                         assign_material(ob, assigned_name, it->second, BKE_MAT_ASSIGN_OBJECT);
777                 }
778         }
779 }
780
781 }  /* namespace utils */
782
783 /* ************************************************************************** */
784
785 using Alembic::AbcGeom::UInt32ArraySamplePtr;
786 using Alembic::AbcGeom::V2fArraySamplePtr;
787
788 struct AbcMeshData {
789         Int32ArraySamplePtr face_indices;
790         Int32ArraySamplePtr face_counts;
791
792         P3fArraySamplePtr positions;
793         P3fArraySamplePtr ceil_positions;
794
795         N3fArraySamplePtr vertex_normals;
796         N3fArraySamplePtr face_normals;
797
798         V2fArraySamplePtr uvs;
799         UInt32ArraySamplePtr uvs_indices;
800 };
801
802 static void *add_customdata_cb(void *user_data, const char *name, int data_type)
803 {
804         Mesh *mesh = static_cast<Mesh *>(user_data);
805         CustomDataType cd_data_type = static_cast<CustomDataType>(data_type);
806         void *cd_ptr = NULL;
807
808         int index = -1;
809         if (cd_data_type == CD_MLOOPUV) {
810                 index = ED_mesh_uv_texture_add(mesh, name, true);
811                 cd_ptr = CustomData_get_layer(&mesh->ldata, cd_data_type);
812         }
813         else if (cd_data_type == CD_MLOOPCOL) {
814                 index = ED_mesh_color_add(mesh, name, true);
815                 cd_ptr = CustomData_get_layer(&mesh->ldata, cd_data_type);
816         }
817
818         if (index == -1) {
819                 return NULL;
820         }
821
822         return cd_ptr;
823 }
824
825 CDStreamConfig create_config(Mesh *mesh)
826 {
827         CDStreamConfig config;
828
829         config.mvert = mesh->mvert;
830         config.mpoly = mesh->mpoly;
831         config.mloop = mesh->mloop;
832         config.totpoly = mesh->totpoly;
833         config.totloop = mesh->totloop;
834         config.user_data = mesh;
835         config.loopdata = &mesh->ldata;
836         config.add_customdata_cb = add_customdata_cb;
837
838         return config;
839 }
840
841 static void read_mverts_interp(MVert *mverts, const P3fArraySamplePtr &positions, const P3fArraySamplePtr &ceil_positions, const float weight)
842 {
843         float tmp[3];
844         for (int i = 0; i < positions->size(); ++i) {
845                 MVert &mvert = mverts[i];
846                 const Imath::V3f &floor_pos = (*positions)[i];
847                 const Imath::V3f &ceil_pos = (*ceil_positions)[i];
848
849                 interp_v3_v3v3(tmp, floor_pos.getValue(), ceil_pos.getValue(), weight);
850                 copy_yup_zup(mvert.co, tmp);
851
852                 mvert.bweight = 0;
853         }
854 }
855
856 static void read_mverts(CDStreamConfig &config, const AbcMeshData &mesh_data)
857 {
858         MVert *mverts = config.mvert;
859         const P3fArraySamplePtr &positions = mesh_data.positions;
860         const N3fArraySamplePtr &normals = mesh_data.vertex_normals;
861
862         if (config.weight != 0.0f && mesh_data.ceil_positions) {
863                 read_mverts_interp(mverts, positions, mesh_data.ceil_positions, config.weight);
864                 return;
865         }
866
867         read_mverts(mverts, positions, normals);
868 }
869
870 void read_mverts(MVert *mverts, const P3fArraySamplePtr &positions, const N3fArraySamplePtr &normals)
871 {
872         for (int i = 0; i < positions->size(); ++i) {
873                 MVert &mvert = mverts[i];
874                 Imath::V3f pos_in = (*positions)[i];
875
876                 copy_yup_zup(mvert.co, pos_in.getValue());
877
878                 mvert.bweight = 0;
879
880                 if (normals) {
881                         Imath::V3f nor_in = (*normals)[i];
882
883                         short no[3];
884                         normal_float_to_short_v3(no, nor_in.getValue());
885
886                         copy_yup_zup(mvert.no, no);
887                 }
888         }
889 }
890
891 static void read_mpolys(CDStreamConfig &config, const AbcMeshData &mesh_data)
892 {
893         MPoly *mpolys = config.mpoly;
894         MLoop *mloops = config.mloop;
895         MLoopUV *mloopuvs = config.mloopuv;
896
897         const Int32ArraySamplePtr &face_indices = mesh_data.face_indices;
898         const Int32ArraySamplePtr &face_counts = mesh_data.face_counts;
899         const V2fArraySamplePtr &uvs = mesh_data.uvs;
900         const UInt32ArraySamplePtr &uvs_indices = mesh_data.uvs_indices;
901         const N3fArraySamplePtr &normals = mesh_data.face_normals;
902
903         const bool do_uvs = (mloopuvs && uvs && uvs_indices) && (uvs_indices->size() == face_indices->size());
904         unsigned int loop_index = 0;
905         unsigned int rev_loop_index = 0;
906         unsigned int uv_index = 0;
907
908         for (int i = 0; i < face_counts->size(); ++i) {
909                 const int face_size = (*face_counts)[i];
910
911                 MPoly &poly = mpolys[i];
912                 poly.loopstart = loop_index;
913                 poly.totloop = face_size;
914
915                 if (normals != NULL) {
916                         poly.flag |= ME_SMOOTH;
917                 }
918
919                 /* NOTE: Alembic data is stored in the reverse order. */
920                 rev_loop_index = loop_index + (face_size - 1);
921
922                 for (int f = 0; f < face_size; ++f, ++loop_index, --rev_loop_index) {
923                         MLoop &loop = mloops[rev_loop_index];
924                         loop.v = (*face_indices)[loop_index];
925
926                         if (do_uvs) {
927                                 MLoopUV &loopuv = mloopuvs[rev_loop_index];
928
929                                 uv_index = (*uvs_indices)[loop_index];
930                                 loopuv.uv[0] = (*uvs)[uv_index][0];
931                                 loopuv.uv[1] = (*uvs)[uv_index][1];
932                         }
933                 }
934         }
935 }
936
937 ABC_INLINE void read_uvs_params(CDStreamConfig &config,
938                                 AbcMeshData &abc_data,
939                                 const IV2fGeomParam &uv,
940                                 const ISampleSelector &selector)
941 {
942         if (!uv.valid()) {
943                 return;
944         }
945
946         IV2fGeomParam::Sample uvsamp;
947         uv.getIndexed(uvsamp, selector);
948
949         abc_data.uvs = uvsamp.getVals();
950         abc_data.uvs_indices = uvsamp.getIndices();
951
952         if (abc_data.uvs_indices->size() == config.totloop) {
953                 std::string name = Alembic::Abc::GetSourceName(uv.getMetaData());
954
955                 /* According to the convention, primary UVs should have had their name
956                  * set using Alembic::Abc::SetSourceName, but you can't expect everyone
957                  * to follow it! :) */
958                 if (name.empty()) {
959                         name = uv.getName();
960                 }
961
962                 void *cd_ptr = config.add_customdata_cb(config.user_data, name.c_str(), CD_MLOOPUV);
963                 config.mloopuv = static_cast<MLoopUV *>(cd_ptr);
964         }
965 }
966
967 /* TODO(kevin): normals from Alembic files are not read in anymore, this is due
968  * to the fact that there are many issues that are not so easy to solve, mainly
969  * regarding the way normals are handled in Blender (MPoly.flag vs loop normals).
970  */
971 ABC_INLINE void read_normals_params(AbcMeshData &abc_data,
972                                     const IN3fGeomParam &normals,
973                                     const ISampleSelector &selector)
974 {
975         if (!normals.valid()) {
976                 return;
977         }
978
979         IN3fGeomParam::Sample normsamp = normals.getExpandedValue(selector);
980
981         if (normals.getScope() == kFacevaryingScope) {
982                 abc_data.face_normals = normsamp.getVals();
983         }
984         else if ((normals.getScope() == kVertexScope) || (normals.getScope() == kVaryingScope)) {
985                 abc_data.vertex_normals = N3fArraySamplePtr();
986         }
987 }
988
989 /* ************************************************************************** */
990
991 AbcMeshReader::AbcMeshReader(const IObject &object, ImportSettings &settings)
992     : AbcObjectReader(object, settings)
993 {
994         m_settings->read_flag |= MOD_MESHSEQ_READ_ALL;
995
996         IPolyMesh ipoly_mesh(m_iobject, kWrapExisting);
997         m_schema = ipoly_mesh.getSchema();
998
999         get_min_max_time(m_iobject, m_schema, m_min_time, m_max_time);
1000 }
1001
1002 bool AbcMeshReader::valid() const
1003 {
1004         return m_schema.valid();
1005 }
1006
1007 void AbcMeshReader::readObjectData(Main *bmain, float time)
1008 {
1009         Mesh *mesh = BKE_mesh_add(bmain, m_data_name.c_str());
1010
1011         m_object = BKE_object_add_only_object(bmain, OB_MESH, m_object_name.c_str());
1012         m_object->data = mesh;
1013
1014         const ISampleSelector sample_sel(time);
1015         const IPolyMeshSchema::Sample sample = m_schema.getValue(sample_sel);
1016
1017         const P3fArraySamplePtr &positions = sample.getPositions();
1018         const Int32ArraySamplePtr &face_indices = sample.getFaceIndices();
1019     const Int32ArraySamplePtr &face_counts = sample.getFaceCounts();
1020
1021         utils::mesh_add_verts(mesh, positions->size());
1022         utils::mesh_add_mpolygons(mesh, face_counts->size());
1023         utils::mesh_add_mloops(mesh, face_indices->size());
1024
1025         m_mesh_data = create_config(mesh);
1026
1027         bool has_smooth_normals = false;
1028         read_mesh_sample(m_settings, m_schema, sample_sel, m_mesh_data, has_smooth_normals);
1029
1030         BKE_mesh_calc_normals(mesh);
1031         BKE_mesh_calc_edges(mesh, false, false);
1032
1033         if (m_settings->validate_meshes) {
1034                 BKE_mesh_validate(mesh, false, false);
1035         }
1036
1037         readFaceSetsSample(bmain, mesh, 0, sample_sel);
1038
1039         if (has_animations(m_schema, m_settings)) {
1040                 addCacheModifier();
1041         }
1042 }
1043
1044 void AbcMeshReader::readFaceSetsSample(Main *bmain, Mesh *mesh, size_t poly_start,
1045                                        const ISampleSelector &sample_sel)
1046 {
1047         std::vector<std::string> face_sets;
1048         m_schema.getFaceSetNames(face_sets);
1049
1050         if (face_sets.empty()) {
1051                 return;
1052         }
1053
1054         std::map<std::string, int> mat_map;
1055         int current_mat = 0;
1056
1057         for (int i = 0; i < face_sets.size(); ++i) {
1058                 const std::string &grp_name = face_sets[i];
1059
1060                 if (mat_map.find(grp_name) == mat_map.end()) {
1061                         mat_map[grp_name] = 1 + current_mat++;
1062                 }
1063
1064                 const int assigned_mat = mat_map[grp_name];
1065
1066                 const IFaceSet faceset = m_schema.getFaceSet(grp_name);
1067
1068                 if (!faceset.valid()) {
1069                         continue;
1070                 }
1071
1072                 const IFaceSetSchema face_schem = faceset.getSchema();
1073                 const IFaceSetSchema::Sample face_sample = face_schem.getValue(sample_sel);
1074                 const Int32ArraySamplePtr group_faces = face_sample.getFaces();
1075                 const size_t num_group_faces = group_faces->size();
1076
1077                 for (size_t l = 0; l < num_group_faces; l++) {
1078                         size_t pos = (*group_faces)[l] + poly_start;
1079
1080                         if (pos >= mesh->totpoly) {
1081                                 std::cerr << "Faceset overflow on " << faceset.getName() << '\n';
1082                                 break;
1083                         }
1084
1085                         MPoly &poly = mesh->mpoly[pos];
1086                         poly.mat_nr = assigned_mat - 1;
1087                 }
1088         }
1089
1090         utils::assign_materials(bmain, m_object, mat_map);
1091 }
1092
1093 static void get_weight_and_index(CDStreamConfig &config,
1094                                  Alembic::AbcCoreAbstract::TimeSamplingPtr time_sampling,
1095                                  size_t samples_number)
1096 {
1097         Alembic::AbcGeom::index_t i0, i1;
1098
1099         config.weight = get_weight_and_index(config.time,
1100                                              time_sampling,
1101                                              samples_number,
1102                                              i0,
1103                                              i1);
1104
1105         config.index = i0;
1106         config.ceil_index = i1;
1107 }
1108
1109 void read_mesh_sample(ImportSettings *settings,
1110                       const IPolyMeshSchema &schema,
1111                       const ISampleSelector &selector,
1112                       CDStreamConfig &config,
1113                       bool &do_normals)
1114 {
1115         const IPolyMeshSchema::Sample sample = schema.getValue(selector);
1116
1117         AbcMeshData abc_mesh_data;
1118         abc_mesh_data.face_counts = sample.getFaceCounts();
1119         abc_mesh_data.face_indices = sample.getFaceIndices();
1120         abc_mesh_data.positions = sample.getPositions();
1121
1122         read_normals_params(abc_mesh_data, schema.getNormalsParam(), selector);
1123
1124         do_normals = (abc_mesh_data.face_normals != NULL);
1125
1126         get_weight_and_index(config, schema.getTimeSampling(), schema.getNumSamples());
1127
1128         if (config.weight != 0.0f) {
1129                 Alembic::AbcGeom::IPolyMeshSchema::Sample ceil_sample;
1130                 schema.get(ceil_sample, Alembic::Abc::ISampleSelector(static_cast<Alembic::AbcCoreAbstract::index_t>(config.ceil_index)));
1131                 abc_mesh_data.ceil_positions = ceil_sample.getPositions();
1132         }
1133
1134         if ((settings->read_flag & MOD_MESHSEQ_READ_UV) != 0) {
1135                 read_uvs_params(config, abc_mesh_data, schema.getUVsParam(), selector);
1136         }
1137
1138         if ((settings->read_flag & MOD_MESHSEQ_READ_VERT) != 0) {
1139                 read_mverts(config, abc_mesh_data);
1140         }
1141
1142         if ((settings->read_flag & MOD_MESHSEQ_READ_POLY) != 0) {
1143                 read_mpolys(config, abc_mesh_data);
1144         }
1145
1146         if ((settings->read_flag & (MOD_MESHSEQ_READ_UV | MOD_MESHSEQ_READ_COLOR)) != 0) {
1147                 read_custom_data(schema.getArbGeomParams(), config, selector);
1148         }
1149
1150         /* TODO: face sets */
1151 }
1152
1153 /* ************************************************************************** */
1154
1155 ABC_INLINE MEdge *find_edge(MEdge *edges, int totedge, int v1, int v2)
1156 {
1157         for (int i = 0, e = totedge; i < e; ++i) {
1158                 MEdge &edge = edges[i];
1159
1160                 if (edge.v1 == v1 && edge.v2 == v2) {
1161                         return &edge;
1162                 }
1163         }
1164
1165         return NULL;
1166 }
1167
1168 AbcSubDReader::AbcSubDReader(const IObject &object, ImportSettings &settings)
1169     : AbcObjectReader(object, settings)
1170 {
1171         m_settings->read_flag |= MOD_MESHSEQ_READ_ALL;
1172
1173         ISubD isubd_mesh(m_iobject, kWrapExisting);
1174         m_schema = isubd_mesh.getSchema();
1175
1176         get_min_max_time(m_iobject, m_schema, m_min_time, m_max_time);
1177 }
1178
1179 bool AbcSubDReader::valid() const
1180 {
1181         return m_schema.valid();
1182 }
1183
1184 void AbcSubDReader::readObjectData(Main *bmain, float time)
1185 {
1186         Mesh *mesh = BKE_mesh_add(bmain, m_data_name.c_str());
1187
1188         m_object = BKE_object_add_only_object(bmain, OB_MESH, m_object_name.c_str());
1189         m_object->data = mesh;
1190
1191         const ISampleSelector sample_sel(time);
1192         const ISubDSchema::Sample sample = m_schema.getValue(sample_sel);
1193
1194         const P3fArraySamplePtr &positions = sample.getPositions();
1195         const Int32ArraySamplePtr &face_indices = sample.getFaceIndices();
1196     const Int32ArraySamplePtr &face_counts = sample.getFaceCounts();
1197
1198         utils::mesh_add_verts(mesh, positions->size());
1199         utils::mesh_add_mpolygons(mesh, face_counts->size());
1200         utils::mesh_add_mloops(mesh, face_indices->size());
1201
1202         m_mesh_data = create_config(mesh);
1203
1204         read_subd_sample(m_settings, m_schema, sample_sel, m_mesh_data);
1205
1206         Int32ArraySamplePtr indices = sample.getCreaseIndices();
1207         Alembic::Abc::FloatArraySamplePtr sharpnesses = sample.getCreaseSharpnesses();
1208
1209         MEdge *edges = mesh->medge;
1210
1211         if (indices && sharpnesses) {
1212                 for (int i = 0, s = 0, e = indices->size(); i < e; i += 2, ++s) {
1213                         MEdge *edge = find_edge(edges, mesh->totedge, (*indices)[i], (*indices)[i + 1]);
1214
1215                         if (edge) {
1216                                 edge->crease = FTOCHAR((*sharpnesses)[s]);
1217                         }
1218                 }
1219
1220                 mesh->cd_flag |= ME_CDFLAG_EDGE_CREASE;
1221         }
1222
1223         BKE_mesh_calc_normals(mesh);
1224         BKE_mesh_calc_edges(mesh, false, false);
1225
1226         if (m_settings->validate_meshes) {
1227                 BKE_mesh_validate(mesh, false, false);
1228         }
1229
1230         if (has_animations(m_schema, m_settings)) {
1231                 addCacheModifier();
1232         }
1233 }
1234
1235 void read_subd_sample(ImportSettings *settings,
1236                       const ISubDSchema &schema,
1237                       const ISampleSelector &selector,
1238                       CDStreamConfig &config)
1239 {
1240         const ISubDSchema::Sample sample = schema.getValue(selector);
1241
1242         AbcMeshData abc_mesh_data;
1243         abc_mesh_data.face_counts = sample.getFaceCounts();
1244         abc_mesh_data.face_indices = sample.getFaceIndices();
1245         abc_mesh_data.vertex_normals = N3fArraySamplePtr();
1246         abc_mesh_data.face_normals = N3fArraySamplePtr();
1247         abc_mesh_data.positions = sample.getPositions();
1248
1249         get_weight_and_index(config, schema.getTimeSampling(), schema.getNumSamples());
1250
1251         if (config.weight != 0.0f) {
1252                 Alembic::AbcGeom::ISubDSchema::Sample ceil_sample;
1253                 schema.get(ceil_sample, Alembic::Abc::ISampleSelector(static_cast<Alembic::AbcCoreAbstract::index_t>(config.ceil_index)));
1254                 abc_mesh_data.ceil_positions = ceil_sample.getPositions();
1255         }
1256
1257         if ((settings->read_flag & MOD_MESHSEQ_READ_UV) != 0) {
1258                 read_uvs_params(config, abc_mesh_data, schema.getUVsParam(), selector);
1259         }
1260
1261         if ((settings->read_flag & MOD_MESHSEQ_READ_VERT) != 0) {
1262                 read_mverts(config, abc_mesh_data);
1263         }
1264
1265         if ((settings->read_flag & MOD_MESHSEQ_READ_POLY) != 0) {
1266                 read_mpolys(config, abc_mesh_data);
1267         }
1268
1269         if ((settings->read_flag & (MOD_MESHSEQ_READ_UV | MOD_MESHSEQ_READ_COLOR)) != 0) {
1270                 read_custom_data(schema.getArbGeomParams(), config, selector);
1271         }
1272
1273         /* TODO: face sets */
1274 }