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