Alembic: added some clarification
[blender.git] / source / blender / alembic / intern / abc_util.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_util.h"
24
25 #include "abc_camera.h"
26 #include "abc_curves.h"
27 #include "abc_mesh.h"
28 #include "abc_nurbs.h"
29 #include "abc_points.h"
30 #include "abc_transform.h"
31
32 #include <Alembic/AbcMaterial/IMaterial.h>
33
34 #include <algorithm>
35
36 extern "C" {
37 #include "DNA_object_types.h"
38
39 #include "BLI_math.h"
40
41 #include "PIL_time.h"
42 }
43
44 std::string get_id_name(Object *ob)
45 {
46         if (!ob) {
47                 return "";
48         }
49
50         return get_id_name(&ob->id);
51 }
52
53 std::string get_id_name(ID *id)
54 {
55         std::string name(id->name + 2);
56         std::replace(name.begin(), name.end(), ' ', '_');
57         std::replace(name.begin(), name.end(), '.', '_');
58         std::replace(name.begin(), name.end(), ':', '_');
59
60         return name;
61 }
62
63 std::string get_object_dag_path_name(Object *ob, Object *dupli_parent)
64 {
65         std::string name = get_id_name(ob);
66
67         Object *p = ob->parent;
68
69         while (p) {
70                 name = get_id_name(p) + "/" + name;
71                 p = p->parent;
72         }
73
74         if (dupli_parent && (ob != dupli_parent)) {
75                 name = get_id_name(dupli_parent) + "/" + name;
76         }
77
78         return name;
79 }
80
81 bool object_selected(Object *ob)
82 {
83         return ob->flag & SELECT;
84 }
85
86 bool parent_selected(Object *ob)
87 {
88         if (object_selected(ob)) {
89                 return true;
90         }
91
92         bool do_export = false;
93
94         Object *parent = ob->parent;
95
96         while (parent != NULL) {
97                 if (object_selected(parent)) {
98                         do_export = true;
99                         break;
100                 }
101
102                 parent = parent->parent;
103         }
104
105         return do_export;
106 }
107
108 Imath::M44d convert_matrix(float mat[4][4])
109 {
110         Imath::M44d m;
111
112         for (int i = 0; i < 4; ++i) {
113                 for (int j = 0; j < 4; ++j) {
114                         m[i][j] = mat[i][j];
115                 }
116         }
117
118         return m;
119 }
120
121 void split(const std::string &s, const char delim, std::vector<std::string> &tokens)
122 {
123         tokens.clear();
124
125         std::stringstream ss(s);
126         std::string item;
127
128         while (std::getline(ss, item, delim)) {
129                 if (!item.empty()) {
130                         tokens.push_back(item);
131                 }
132         }
133 }
134
135 /* Create a rotation matrix for each axis from euler angles.
136  * Euler angles are swaped to change coordinate system. */
137 static void create_rotation_matrix(
138         float rot_x_mat[3][3], float rot_y_mat[3][3],
139         float rot_z_mat[3][3], const float euler[3], const bool to_yup)
140 {
141         const float rx = euler[0];
142         const float ry = (to_yup) ?  euler[2] : -euler[2];
143         const float rz = (to_yup) ? -euler[1] :  euler[1];
144
145         unit_m3(rot_x_mat);
146         unit_m3(rot_y_mat);
147         unit_m3(rot_z_mat);
148
149         rot_x_mat[1][1] = cos(rx);
150         rot_x_mat[2][1] = -sin(rx);
151         rot_x_mat[1][2] = sin(rx);
152         rot_x_mat[2][2] = cos(rx);
153
154         rot_y_mat[2][2] = cos(ry);
155         rot_y_mat[0][2] = -sin(ry);
156         rot_y_mat[2][0] = sin(ry);
157         rot_y_mat[0][0] = cos(ry);
158
159         rot_z_mat[0][0] = cos(rz);
160         rot_z_mat[1][0] = -sin(rz);
161         rot_z_mat[0][1] = sin(rz);
162         rot_z_mat[1][1] = cos(rz);
163 }
164
165 /* Recompute transform matrix of object in new coordinate system
166  * (from Y-Up to Z-Up).
167  *
168  * Note that r_mat is used as both input and output parameter.
169  */
170 void create_transform_matrix(float r_mat[4][4])
171 {
172         float rot_mat[3][3], rot[3][3], scale_mat[4][4], invmat[4][4], transform_mat[4][4];
173         float rot_x_mat[3][3], rot_y_mat[3][3], rot_z_mat[3][3];
174         float loc[3], scale[3], euler[3];
175
176         zero_v3(loc);
177         zero_v3(scale);
178         zero_v3(euler);
179         unit_m3(rot);
180         unit_m3(rot_mat);
181         unit_m4(scale_mat);
182         unit_m4(transform_mat);
183         unit_m4(invmat);
184
185         /* Compute rotation matrix. */
186
187         /* Extract location, rotation, and scale from matrix. */
188         mat4_to_loc_rot_size(loc, rot, scale, r_mat);
189
190         /* Get euler angles from rotation matrix. */
191         mat3_to_eulO(euler, ROT_MODE_XYZ, rot);
192
193         /* Create X, Y, Z rotation matrices from euler angles. */
194         create_rotation_matrix(rot_x_mat, rot_y_mat, rot_z_mat, euler, false);
195
196         /* Concatenate rotation matrices. */
197         mul_m3_m3m3(rot_mat, rot_mat, rot_y_mat);
198         mul_m3_m3m3(rot_mat, rot_mat, rot_z_mat);
199         mul_m3_m3m3(rot_mat, rot_mat, rot_x_mat);
200
201         /* Add rotation matrix to transformation matrix. */
202         copy_m4_m3(transform_mat, rot_mat);
203
204         /* Add translation to transformation matrix. */
205         copy_zup_from_yup(transform_mat[3], loc);
206
207         /* Create scale matrix. */
208         scale_mat[0][0] = scale[0];
209         scale_mat[1][1] = scale[2];
210         scale_mat[2][2] = scale[1];
211
212         /* Add scale to transformation matrix. */
213         mul_m4_m4m4(transform_mat, transform_mat, scale_mat);
214
215         copy_m4_m4(r_mat, transform_mat);
216 }
217
218 void convert_matrix(const Imath::M44d &xform, Object *ob,
219                     float r_mat[4][4], float scale, bool has_alembic_parent)
220 {
221         for (int i = 0; i < 4; ++i) {
222                 for (int j = 0; j < 4; ++j) {
223                         r_mat[i][j] = static_cast<float>(xform[i][j]);
224                 }
225         }
226
227         if (ob->type == OB_CAMERA) {
228                 float cam_to_yup[4][4];
229                 axis_angle_to_mat4_single(cam_to_yup, 'X', M_PI_2);
230                 mul_m4_m4m4(r_mat, r_mat, cam_to_yup);
231         }
232
233         create_transform_matrix(r_mat);
234
235         if (ob->parent) {
236                 mul_m4_m4m4(r_mat, ob->parent->obmat, r_mat);
237         }
238         /* TODO(kevin) */
239         else if (!has_alembic_parent) {
240                 /* Only apply scaling to root objects, parenting will propagate it. */
241                 float scale_mat[4][4];
242                 scale_m4_fl(scale_mat, scale);
243                 mul_m4_m4m4(r_mat, r_mat, scale_mat);
244                 mul_v3_fl(r_mat[3], scale);
245         }
246 }
247
248 /* Recompute transform matrix of object in new coordinate system (from Z-Up to Y-Up). */
249 void create_transform_matrix(Object *obj, float transform_mat[4][4])
250 {
251         float rot_mat[3][3], rot[3][3], scale_mat[4][4], invmat[4][4], mat[4][4];
252         float rot_x_mat[3][3], rot_y_mat[3][3], rot_z_mat[3][3];
253         float loc[3], scale[3], euler[3];
254
255         zero_v3(loc);
256         zero_v3(scale);
257         zero_v3(euler);
258         unit_m3(rot);
259         unit_m3(rot_mat);
260         unit_m4(scale_mat);
261         unit_m4(transform_mat);
262         unit_m4(invmat);
263         unit_m4(mat);
264
265         /* get local matrix. */
266         if (obj->parent) {
267                 invert_m4_m4(invmat, obj->parent->obmat);
268                 mul_m4_m4m4(mat, invmat, obj->obmat);
269         }
270         else {
271                 copy_m4_m4(mat, obj->obmat);
272         }
273
274         /* Compute rotation matrix. */
275         switch (obj->rotmode) {
276                 case ROT_MODE_AXISANGLE:
277                 {
278                         /* Get euler angles from axis angle rotation. */
279                         axis_angle_to_eulO(euler, ROT_MODE_XYZ, obj->rotAxis, obj->rotAngle);
280
281                         /* Create X, Y, Z rotation matrices from euler angles. */
282                         create_rotation_matrix(rot_x_mat, rot_y_mat, rot_z_mat, euler, true);
283
284                         /* Concatenate rotation matrices. */
285                         mul_m3_m3m3(rot_mat, rot_mat, rot_y_mat);
286                         mul_m3_m3m3(rot_mat, rot_mat, rot_z_mat);
287                         mul_m3_m3m3(rot_mat, rot_mat, rot_x_mat);
288
289                         /* Extract location and scale from matrix. */
290                         mat4_to_loc_rot_size(loc, rot, scale, mat);
291
292                         break;
293                 }
294                 case ROT_MODE_QUAT:
295                 {
296                         float q[4];
297                         copy_v4_v4(q, obj->quat);
298
299                         /* Swap axis. */
300                         q[2] = obj->quat[3];
301                         q[3] = -obj->quat[2];
302
303                         /* Compute rotation matrix from quaternion. */
304                         quat_to_mat3(rot_mat, q);
305
306                         /* Extract location and scale from matrix. */
307                         mat4_to_loc_rot_size(loc, rot, scale, mat);
308
309                         break;
310                 }
311                 case ROT_MODE_XYZ:
312                 {
313                         /* Extract location, rotation, and scale form matrix. */
314                         mat4_to_loc_rot_size(loc, rot, scale, mat);
315
316                         /* Get euler angles from rotation matrix. */
317                         mat3_to_eulO(euler, ROT_MODE_XYZ, rot);
318
319                         /* Create X, Y, Z rotation matrices from euler angles. */
320                         create_rotation_matrix(rot_x_mat, rot_y_mat, rot_z_mat, euler, true);
321
322                         /* Concatenate rotation matrices. */
323                         mul_m3_m3m3(rot_mat, rot_mat, rot_y_mat);
324                         mul_m3_m3m3(rot_mat, rot_mat, rot_z_mat);
325                         mul_m3_m3m3(rot_mat, rot_mat, rot_x_mat);
326
327                         break;
328                 }
329                 case ROT_MODE_XZY:
330                 {
331                         /* Extract location, rotation, and scale form matrix. */
332                         mat4_to_loc_rot_size(loc, rot, scale, mat);
333
334                         /* Get euler angles from rotation matrix. */
335                         mat3_to_eulO(euler, ROT_MODE_XZY, rot);
336
337                         /* Create X, Y, Z rotation matrices from euler angles. */
338                         create_rotation_matrix(rot_x_mat, rot_y_mat, rot_z_mat, euler, true);
339
340                         /* Concatenate rotation matrices. */
341                         mul_m3_m3m3(rot_mat, rot_mat, rot_z_mat);
342                         mul_m3_m3m3(rot_mat, rot_mat, rot_y_mat);
343                         mul_m3_m3m3(rot_mat, rot_mat, rot_x_mat);
344
345                         break;
346                 }
347                 case ROT_MODE_YXZ:
348                 {
349                         /* Extract location, rotation, and scale form matrix. */
350                         mat4_to_loc_rot_size(loc, rot, scale, mat);
351
352                         /* Get euler angles from rotation matrix. */
353                         mat3_to_eulO(euler, ROT_MODE_YXZ, rot);
354
355                         /* Create X, Y, Z rotation matrices from euler angles. */
356                         create_rotation_matrix(rot_x_mat, rot_y_mat, rot_z_mat, euler, true);
357
358                         /* Concatenate rotation matrices. */
359                         mul_m3_m3m3(rot_mat, rot_mat, rot_y_mat);
360                         mul_m3_m3m3(rot_mat, rot_mat, rot_x_mat);
361                         mul_m3_m3m3(rot_mat, rot_mat, rot_z_mat);
362
363                         break;
364                 }
365                 case ROT_MODE_YZX:
366                 {
367                         /* Extract location, rotation, and scale form matrix. */
368                         mat4_to_loc_rot_size(loc, rot, scale, mat);
369
370                         /* Get euler angles from rotation matrix. */
371                         mat3_to_eulO(euler, ROT_MODE_YZX, rot);
372
373                         /* Create X, Y, Z rotation matrices from euler angles. */
374                         create_rotation_matrix(rot_x_mat, rot_y_mat, rot_z_mat, euler, true);
375
376                         /* Concatenate rotation matrices. */
377                         mul_m3_m3m3(rot_mat, rot_mat, rot_x_mat);
378                         mul_m3_m3m3(rot_mat, rot_mat, rot_y_mat);
379                         mul_m3_m3m3(rot_mat, rot_mat, rot_z_mat);
380
381                         break;
382                 }
383                 case ROT_MODE_ZXY:
384                 {
385                         /* Extract location, rotation, and scale form matrix. */
386                         mat4_to_loc_rot_size(loc, rot, scale, mat);
387
388                         /* Get euler angles from rotation matrix. */
389                         mat3_to_eulO(euler, ROT_MODE_ZXY, rot);
390
391                         /* Create X, Y, Z rotation matrices from euler angles. */
392                         create_rotation_matrix(rot_x_mat, rot_y_mat, rot_z_mat, euler, true);
393
394                         /* Concatenate rotation matrices. */
395                         mul_m3_m3m3(rot_mat, rot_mat, rot_z_mat);
396                         mul_m3_m3m3(rot_mat, rot_mat, rot_x_mat);
397                         mul_m3_m3m3(rot_mat, rot_mat, rot_y_mat);
398
399                         break;
400                 }
401                 case ROT_MODE_ZYX:
402                 {
403                         /* Extract location, rotation, and scale form matrix. */
404                         mat4_to_loc_rot_size(loc, rot, scale, mat);
405
406                         /* Get euler angles from rotation matrix. */
407                         mat3_to_eulO(euler, ROT_MODE_ZYX, rot);
408
409                         /* Create X, Y, Z rotation matrices from euler angles. */
410                         create_rotation_matrix(rot_x_mat, rot_y_mat, rot_z_mat, euler, true);
411
412                         /* Concatenate rotation matrices. */
413                         mul_m3_m3m3(rot_mat, rot_mat, rot_x_mat);
414                         mul_m3_m3m3(rot_mat, rot_mat, rot_z_mat);
415                         mul_m3_m3m3(rot_mat, rot_mat, rot_y_mat);
416
417                         break;
418                 }
419         }
420
421         /* Add rotation matrix to transformation matrix. */
422         copy_m4_m3(transform_mat, rot_mat);
423
424         /* Add translation to transformation matrix. */
425         copy_yup_from_zup(transform_mat[3], loc);
426
427         /* Create scale matrix. */
428         scale_mat[0][0] = scale[0];
429         scale_mat[1][1] = scale[2];
430         scale_mat[2][2] = scale[1];
431
432         /* Add scale to transformation matrix. */
433         mul_m4_m4m4(transform_mat, transform_mat, scale_mat);
434 }
435
436 bool has_property(const Alembic::Abc::ICompoundProperty &prop, const std::string &name)
437 {
438         if (!prop.valid()) {
439                 return false;
440         }
441
442         return prop.getPropertyHeader(name) != NULL;
443 }
444
445 typedef std::pair<Alembic::AbcCoreAbstract::index_t, float> index_time_pair_t;
446
447 float get_weight_and_index(float time,
448                            const Alembic::AbcCoreAbstract::TimeSamplingPtr &time_sampling,
449                            int samples_number,
450                            Alembic::AbcGeom::index_t &i0,
451                            Alembic::AbcGeom::index_t &i1)
452 {
453         samples_number = std::max(samples_number, 1);
454
455         index_time_pair_t t0 = time_sampling->getFloorIndex(time, samples_number);
456         i0 = i1 = t0.first;
457
458         if (samples_number == 1 || (fabs(time - t0.second) < 0.0001f)) {
459                 return 0.0f;
460         }
461
462         index_time_pair_t t1 = time_sampling->getCeilIndex(time, samples_number);
463         i1 = t1.first;
464
465         if (i0 == i1) {
466                 return 0.0f;
467         }
468
469         const float bias = (time - t0.second) / (t1.second - t0.second);
470
471         if (fabs(1.0f - bias) < 0.0001f) {
472                 i0 = i1;
473                 return 0.0f;
474         }
475
476         return bias;
477 }
478
479 //#define USE_NURBS
480
481 AbcObjectReader *create_reader(const Alembic::AbcGeom::IObject &object, ImportSettings &settings)
482 {
483         AbcObjectReader *reader = NULL;
484
485         const Alembic::AbcGeom::MetaData &md = object.getMetaData();
486
487         if (Alembic::AbcGeom::IXform::matches(md)) {
488                 reader = new AbcEmptyReader(object, settings);
489         }
490         else if (Alembic::AbcGeom::IPolyMesh::matches(md)) {
491                 reader = new AbcMeshReader(object, settings);
492         }
493         else if (Alembic::AbcGeom::ISubD::matches(md)) {
494                 reader = new AbcSubDReader(object, settings);
495         }
496         else if (Alembic::AbcGeom::INuPatch::matches(md)) {
497 #ifdef USE_NURBS
498                 /* TODO(kevin): importing cyclic NURBS from other software crashes
499                  * at the moment. This is due to the fact that NURBS in other
500                  * software have duplicated points which causes buffer overflows in
501                  * Blender. Need to figure out exactly how these points are
502                  * duplicated, in all cases (cyclic U, cyclic V, and cyclic UV).
503                  * Until this is fixed, disabling NURBS reading. */
504                 reader = new AbcNurbsReader(child, settings);
505 #endif
506         }
507         else if (Alembic::AbcGeom::ICamera::matches(md)) {
508                 reader = new AbcCameraReader(object, settings);
509         }
510         else if (Alembic::AbcGeom::IPoints::matches(md)) {
511                 reader = new AbcPointsReader(object, settings);
512         }
513         else if (Alembic::AbcMaterial::IMaterial::matches(md)) {
514                 /* Pass for now. */
515         }
516         else if (Alembic::AbcGeom::ILight::matches(md)) {
517                 /* Pass for now. */
518         }
519         else if (Alembic::AbcGeom::IFaceSet::matches(md)) {
520                 /* Pass, those are handled in the mesh reader. */
521         }
522         else if (Alembic::AbcGeom::ICurves::matches(md)) {
523                 reader = new AbcCurveReader(object, settings);
524         }
525         else {
526                 assert(false);
527         }
528
529         return reader;
530 }
531
532 /* ********************** */
533
534 ScopeTimer::ScopeTimer(const char *message)
535         : m_message(message)
536         , m_start(PIL_check_seconds_timer())
537 {}
538
539 ScopeTimer::~ScopeTimer()
540 {
541         fprintf(stderr, "%s: %fs\n", m_message, PIL_check_seconds_timer() - m_start);
542 }
543
544 /* ********************** */
545
546 bool SimpleLogger::empty()
547 {
548         return ((size_t)m_stream.tellp()) == 0ul;
549 }
550
551 std::string SimpleLogger::str() const
552 {
553         return m_stream.str();
554 }
555
556 void SimpleLogger::clear()
557 {
558         m_stream.clear();
559         m_stream.str("");
560 }
561
562 std::ostringstream &SimpleLogger::stream()
563 {
564         return m_stream;
565 }
566
567 std::ostream &operator<<(std::ostream &os, const SimpleLogger &logger)
568 {
569         os << logger.str();
570         return os;
571 }