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