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