Tucano  0.1
A library for rapid prototyping with modern OpenGL and GLSL
path.hpp
Go to the documentation of this file.
1 
23 #ifndef __PATH__
24 #define __PATH__
25 
26 #include <tucano/camera.hpp>
27 #include <tucano/mesh.hpp>
29 #include <tucano/shapes/sphere.hpp>
30 #include <Eigen/Dense>
31 #include <cmath>
32 
33 namespace Tucano
34 {
35 
36 
51 class Path: public Tucano::Camera {
52 
53 private:
54 
56  float anim_speed = 0.025;
57 
59  float anim_time = 0.0;
60 
62  bool animating = false;
63 
65  bool loop_animation = false;
66 
68  bool draw_control_points = false;
69 
71  bool draw_quaternions = false;
72 
74  vector< Eigen::Vector4f > key_positions;
75 
77  vector< float > key_intervals;
78 
80  vector< Eigen::Vector4f > control_points_1;
81 
83  vector< Eigen::Vector4f > control_points_2;
84 
86  vector< vector <float> > arc_lengths;
87 
89  float path_length;
90 
92  vector< Eigen::Quaternion<float> > key_quaternions;
93 
95  vector < Eigen::Quaternion<float> > control_quaternions;
96 
98  vector< Eigen::Quaternion<float> > key_directions;
99 
103 
104  // Mesh containing segments from key points to control points, for visual debug
106 
109 
112 
115 
118 
119 public:
120 
124  Path ()
125  {
127 
128  #ifdef TUCANOSHADERDIR
129  initialize(stringify(TUCANOSHADERDIR));
130  #endif
131  }
132 
136  void reset (void)
137  {
138  key_positions.clear();
139  key_quaternions.clear();
140  key_directions.clear();
141  control_points_1.clear();
142  control_points_2.clear();
143  arc_lengths.clear();
144  path_length = 0.0;
145  }
146 
151  void initOpenGLMatrices (void)
152  {
153  // reset all matrices
154  reset();
155  }
156 
161  void initialize (string shader_dir = "../effects/shaders/")
162  {
163  camerapath_shader.load("beziercurve", shader_dir);
164  camerapath_shader.initialize();
165 
166  phong_shader.load("phongshader", shader_dir);
167  phong_shader.initialize();
168  }
169 
173  void fillVertexData (void)
174  {
177 // insertPausePositions();
179 
180  curve = Mesh();
181  curve.loadVertices(key_positions);
182  curve.createAttribute("in_ControlPoint1", control_points_1);
183  curve.createAttribute("in_ControlPoint2", control_points_2);
184 
185  control_segments = Mesh();
186 
187  vector < Eigen::Vector4f > control_segs;
188  for (unsigned int i = 0; i < key_positions.size()-1; ++i)
189  {
190  control_segs.push_back(key_positions[i]);
191  control_segs.push_back(control_points_1[i]);
192  control_segs.push_back(key_positions[i+1]);
193  control_segs.push_back(control_points_2[i]);
194  }
195  control_segments.loadVertices(control_segs);
196 
197  #ifdef TUCANODEBUG
198  Misc::errorCheckFunc(__FILE__, __LINE__);
199  #endif
200 
201  }
202 
209  void addKeyPosition (const Tucano::Camera& camera, float interval = 0.0)
210  {
211  Eigen::Vector4f center;
212  center << camera.getCenter(), 1.0;
213  key_positions.push_back ( center );
214  key_intervals.push_back ( interval );
215  Eigen::Quaternionf quat (camera.getViewMatrix().rotation() );
216  key_quaternions.push_back (quat.inverse());
217 
218  // if this is a pause pos don't compute yet, wait for next key
219  if (key_positions.size() > 1 && interval == 0.0)
220  fillVertexData();
221 
222  }
223 
231  void addKeyDirection (const Eigen::Quaternion<float> q)
232  {
233  key_directions.push_back ( q );
234  }
235 
236 
245  void render (const Tucano::Camera& camera, const Tucano::Camera& light)
246  {
247  glEnable(GL_DEPTH_TEST);
248  if (key_positions.size() > 1)
249  {
250 
251  // draw path
252  camerapath_shader.bind();
253 
254  camerapath_shader.setUniform("viewMatrix", camera.getViewMatrix());
255  camerapath_shader.setUniform("projectionMatrix", camera.getProjectionMatrix());
256  camerapath_shader.setUniform("nearPlane", camera.getNearPlane());
257  camerapath_shader.setUniform("farPlane", camera.getFarPlane());
258 
259  Eigen::Vector4f color (1.0, 0.0, 0.0, 1.0);
260  camerapath_shader.setUniform("modelMatrix", Eigen::Affine3f::Identity());
261  camerapath_shader.setUniform("in_Color", color);
262 
263  curve.setAttributeLocation(camerapath_shader);
264  curve.bindBuffers();
265  glDrawArrays(GL_LINE_STRIP, 0, key_positions.size());
266  curve.unbindBuffers();
267 
268  camerapath_shader.unbind();
269 
270  if (draw_control_points)
271  {
272  phong_shader.bind();
273 
274  phong_shader.setUniform("viewMatrix", camera.getViewMatrix());
275  phong_shader.setUniform("projectionMatrix", camera.getProjectionMatrix());
276  phong_shader.setUniform("lightViewMatrix", light.getViewMatrix());
277 
278  color << 1.0, 1.0, 0.0, 1.0;
279  phong_shader.setUniform("modelMatrix", Eigen::Affine3f::Identity());
280  phong_shader.setUniform("default_color", color);
281  phong_shader.setUniform("has_color", false);
282  control_segments.setAttributeLocation(phong_shader);
283  control_segments.bindBuffers();
284  glDrawArrays(GL_LINES, 0, control_points_1.size()*4);
285  control_segments.unbindBuffers();
286  phong_shader.unbind();
287 
288  sphere.setColor( Eigen::Vector4f (0.48, 1.0, 0.16, 1.0) );
289  // render control points
290  for (unsigned int i = 0; i < control_points_1.size(); i++)
291  {
292  sphere.resetModelMatrix();
293  Eigen::Vector3f translation = control_points_1[i].head(3);
294  sphere.modelMatrix()->translate( translation );
295  sphere.modelMatrix()->scale( 0.03 );
296  sphere.render(camera, light);
297  }
298 
299  sphere.setColor( Eigen::Vector4f (0.48, 0.16, 1.0, 1.0) );
300  // render control points
301  for (unsigned int i = 0; i < control_points_2.size(); i++)
302  {
303  sphere.resetModelMatrix();
304  Eigen::Vector3f translation = control_points_2[i].head(3);
305  sphere.modelMatrix()->translate( translation );
306  sphere.modelMatrix()->scale( 0.03 );
307  sphere.render(camera, light);
308  }
309 
310  }
311 
312  }
313 
314  if (draw_quaternions)
315  {
316  for (unsigned int i = 0; i < key_quaternions.size(); ++i)
317  {
318  axes.resetModelMatrix();
319  axes.modelMatrix()->rotate(key_quaternions[i]);
320  axes.modelMatrix()->scale(0.2);
321  axes.render(camera, light);
322  }
323  }
324 
325  sphere.setColor( Eigen::Vector4f (1.0, 0.48, 0.16, 1.0) );
326  // render key positions
327  for (unsigned int i = 0; i < key_positions.size(); i++)
328  {
329  sphere.resetModelMatrix();
330 
331  Eigen::Vector3f translation = key_positions[i].head(3);
332  sphere.modelMatrix()->translate( translation );
333  sphere.modelMatrix()->scale( 0.03 );
334  sphere.render(camera, light);
335  }
336 
337 
338  glDisable(GL_DEPTH_TEST);
339 
340  #ifdef TUCANODEBUG
341  Misc::errorCheckFunc(__FILE__, __LINE__);
342  #endif
343  }
344 
349  int curveSegment (float t)
350  {
351  if (t < 0 || t > 1.0)
352  return 0;
353 
354  return int (t * (key_positions.size()-1));
355  }
356 
361  float toLocalParameter (float t)
362  {
363  int segment = curveSegment(t);
364  float segment_length = 1.0 / (float)(key_positions.size()-1);
365 
366  return (t - segment*segment_length)/segment_length;
367  }
368 
375  Eigen::Vector4f pointOnSegment (float t, int segment)
376  {
377  Eigen::Vector4f pt;
378  pt = pow(1-t,3)*key_positions[segment] + 3.0*pow(1-t,2)*t*control_points_1[segment] + 3.0*(1-t)*pow(t,2)*control_points_2[segment] + pow(t, 3)*key_positions[segment+1];
379  return pt;
380  }
381 
389  Eigen::Vector4f pointOnPath (float global_t)
390  {
391  float t = toLocalParameter (global_t);
392  int segment = curveSegment (global_t);
393  return pointOnSegment(t, segment);
394  }
395 
402  Eigen::Quaternionf logQuaternion (const Eigen::Quaternionf& qi)
403  {
404  Eigen::Quaternionf logq, q;
405  q = qi;
406 
407  // change sign to avoid flipping behavior during interpolation
408  if (q.w() < 0)
409  q.coeffs() *= -1.0;
410 
411  logq.w() = 0.0;
412  float angle = acos(q.w());
413  float sinangle = sin(angle);
414  if ( fabs(sinangle) >= 1e-03)
415  logq.vec() = angle * q.vec() / sinangle;
416  else
417  logq.vec() = q.vec();
418 
419 // logq.w() = log ( q.norm() );
420 // logq.vec() = q.vec().normalized() * acos ( q.w() / q.norm());
421 
422  return logq;
423  }
424 
431  Eigen::Quaternionf expQuaternion (const Eigen::Quaternionf& q)
432  {
433  Eigen::Quaternionf expq;
434 
435  float angle = q.norm();
436  expq.w() = cos(angle);
437  float sinangle = sin(angle);
438  if (fabs(sinangle) >= 1e-03)
439  expq.vec() = sin(angle) * q.vec() / angle;
440  else
441  expq.vec() = q.vec();
442 
443 // expq.w() = exp(q.w()) * cos( q.vec().norm() );
444 // expq.vec() = exp(q.w()) * q.vec().normalized() * sin( q.vec().norm() );
445 
446  return expq;
447  }
448 
454  Eigen::Quaternionf squad (int seg, float t)
455  {
456  Eigen::Quaternionf s0 = control_quaternions[seg];
457  Eigen::Quaternionf s1 = control_quaternions[seg+1];
458  Eigen::Quaternionf q0 = key_quaternions[seg];
459  Eigen::Quaternionf q1 = key_quaternions[seg+1];
460  Eigen::Quaternionf p0, p1, res;
461  float dot = 0.0;
462 
463  // before each slerp check if we are going the right direction (shortest path)
464  // otherwise multiply one of the quaternions by -1
465  // Note: this might not be necessary any more, since we are checking during log method
466 
467  dot = q0.w()*q1.w()+q0.vec().dot(q1.vec());
468  if (dot < 0)
469  {
470  q1.coeffs() *= -1.0;
471  }
472  p0 = q0.slerp(t, q1);
473 
474  dot = s0.w()*s1.w()+s0.vec().dot(s1.vec());
475  if (dot < 0)
476  {
477  s1.coeffs() *= -1.0;
478  }
479  p1 = s0.slerp(t, s1);
480 
481  p0.normalize();
482  p1.normalize();
483 
484  dot = p0.w()*p1.w()+p0.vec().dot(p1.vec());
485  if (dot < 0)
486  {
487  p1.coeffs() *= -1.0;
488  }
489  res = p0.slerp(2.0*t*(1.0-t), p1);
490  res.normalize();
491 
492  return res;
493  }
494 
495 
500  Eigen::Affine3f cameraAtTime (float global_t)
501  {
502  Eigen::Affine3f m = Eigen::Affine3f::Identity();
503 
504  float t_a = arcLengthToTime(global_t);
505  if (t_a == -1.0)
506  return m;
507 
508  float t = toLocalParameter (t_a);
509  int segment = curveSegment (t_a);
510 
511  Eigen::Vector4f pt;
512  Eigen::Quaternionf qt;
513  // check if this a pause key position
514  if (key_intervals[segment] > 0.0)
515  {
516  pt = key_positions[segment];
517  qt = key_quaternions[segment];
518  }
519  else
520  {
521  pt = pointOnSegment(t, segment);
522  qt = squad(segment, t);
523 
524  }
525 
526  m.rotate(qt);
527  m.translation() = pt.head(3);
528 
529  return m;
530  }
531 
536  Eigen::Quaternion<float> directionAtTime (float global_t)
537  {
538  Eigen::Quaternion<float> q = Eigen::Quaternion<float>::Identity();
539 
540  float t_a = arcLengthToTime(global_t);
541  if (t_a == -1.0)
542  return q;
543 
544  float t = toLocalParameter (t_a);
545  int segment = curveSegment (t_a);
546 
547  q = key_directions[segment].slerp(t, key_directions[segment+1]);
548 
549  return q;
550  }
555  Eigen::Affine3f cameraAtCurrentTime (void)
556  {
557  return cameraAtTime(anim_time);
558  }
559 
564  Eigen::Quaternion<float> directionAtCurrentTime (void)
565  {
566  return directionAtTime(anim_time);
567  }
568 
574  float arcLengthToTime (float s)
575  {
576  if (key_positions.size() < 2)
577  return -1.0;
578 
579  if (s < 0.0)
580  return 0;
581 
582  if (s > path_length)
583  return path_length;
584 
585  float arc_length = s;
586 
587  // find in which Beziér segment we should look
588  unsigned int segment = 0;
589  for (; segment < key_positions.size()-1; ++segment)
590  {
591  if (arc_lengths[segment+1][0] > arc_length)
592  break;
593  }
594 
595  // look inside Beziér segment in which linear approximation we should look for
596  unsigned int sub_seg = 0;
597  for (; sub_seg < arc_lengths[segment].size()-1; ++sub_seg)
598  {
599  if (arc_lengths[segment][sub_seg+1] > arc_length)
600  break;
601  }
602 
603  // convert from arc length (s) to time parameter (t)
604  // percentage inside sub segment
605  float alpha = (arc_length - arc_lengths[segment][sub_seg]) /
606  (arc_lengths[segment][sub_seg+1] - arc_lengths[segment][sub_seg]);
607 
608  // find parameter [0,1] inside Beziér segment
609  float t_ini = sub_seg / (float)(arc_lengths[segment].size()-1);
610  float t_end = (sub_seg+1) / (float)(arc_lengths[segment].size()-1);
611  float t_s = t_ini + alpha * (t_end - t_ini);
612 
613  // convert to global parameter of the path
614  t_s = t_s / (float)(key_positions.size()-1);
615 
616  // add time to beginning of segment
617  t_s += segment / (float)(key_positions.size()-1);
618 
619  return t_s;
620  }
621 
625  void toggleAnimation (void)
626  {
627  animating = !animating;
628  }
629 
634  void setLoopAnimation (bool f)
635  {
636  loop_animation = f;
637  }
638 
643  {
644  draw_control_points = !draw_control_points;
645  }
646 
651  {
652  draw_quaternions = !draw_quaternions;
653  }
654 
655 
660  bool isAnimating (void)
661  {
662  return animating;
663  }
664 
668  void stepForward ( void )
669  {
670  anim_time += anim_speed;
671  // restart if necessary
672  if (anim_time >= path_length)
673  {
674  if (loop_animation)
675  anim_time = anim_time - path_length;
676  else
677  {
678  anim_time -= anim_speed;
679  animating = false;
680  }
681  }
682  }
683 
687  void stepBackward ( void )
688  {
689  anim_time -= anim_speed;
690  // restart if necessary
691  if (anim_time < 0.0)
692  {
693  anim_time = anim_time + path_length;
694  }
695  }
699  void startAnimation ( void )
700  {
701  animating = true;
702  }
703 
707  void stopAnimation ( void )
708  {
709  animating = false;
710  }
711 
715  void resetAnimation ( void )
716  {
717  anim_time = 0.0;
718  }
719 
724  float animTime ( void )
725  {
726  return anim_time;
727  }
728 
733  float animSpeed ( void )
734  {
735  return anim_speed;
736  }
737 
742  void setAnimSpeed (float as)
743  {
744  anim_speed = as;
745  }
746 
753  {
754  control_quaternions.clear();
755 
756  Eigen::Quaternionf s;
757 
758  // s for first control point is not defined, so we just set as q0
759  s = key_quaternions[0];
760  control_quaternions.push_back(s);
761 
762  for (unsigned int seg = 1; seg < key_quaternions.size()-1; ++seg)
763  {
764  s = -0.25*(logQuaternion(key_quaternions[seg].inverse()*key_quaternions[seg-1]).coeffs() + logQuaternion(key_quaternions[seg].inverse()*key_quaternions[seg+1]).coeffs());
765  s = key_quaternions[seg]* expQuaternion(s);
766 
767  control_quaternions.push_back(s);
768  }
769 
770  // control point for last quaternion not defined since we dont have qi+1
771  control_quaternions.push_back(key_quaternions.back());
772 
773  }
774 
775 
788  {
789 
790  control_points_1.clear();
791  control_points_2.clear();
792 
793  // if there are only two keypoints it is a linear segment
794  // just distribute control points equally along segment
795  if (key_positions.size() == 2)
796  {
797  Eigen::Vector4f pt = 0.75*key_positions[0] + 0.25*key_positions[1];
798  control_points_1.push_back(pt);
799  control_points_1.push_back(pt);
800  pt << 0.25*key_positions[0] + 0.75*key_positions[1];
801  control_points_2.push_back(pt);
802  control_points_2.push_back(pt);
803  return;
804  }
805 
806  const int n = key_positions.size()-1;
807 
808  control_points_1.resize(n+1);
809  control_points_2.resize(n+1);
810 
811  // in theory this should be a nxn matrix, but since it is a tridiagonal matrix
812  // we are just storing the non-zero elements as a, b, and c
813  vector <float> a_orig;
814  vector <float> b_orig;
815  vector <float> c_orig;
816  vector <float> a;
817  vector <float> b;
818  vector <float> c;
819  vector <float> d;
820  a_orig.resize(n);
821  b_orig.resize(n);
822  c_orig.resize(n);
823  a.resize(n);
824  b.resize(n);
825  c.resize(n);
826  d.resize(n);
827 
828  // build the weight matrix, it is the same for all lines except first and last
829  a_orig[0] = 0.0;
830  b_orig[0] = 2.0;
831  c_orig[0] = 1.0;
832 
833  for (int i = 1; i < n-1; i++)
834  {
835  a_orig[i] = 1.0;
836  b_orig[i] = 4.0;
837  c_orig[i] = 1.0;
838  }
839 
840  a_orig[n-1] = 2.0;
841  b_orig[n-1] = 7.0;
842  c_orig[n-1] = 0.0;
843 
844  // solve using Thomas Algorithm for tridiagonal matrices
845  // solve the system three times, one for each coordinate (x, y, and z)
846  // we copy the coefficients each time to avoid recomputing them
847  for (int coord = 0; coord < 3; ++coord)
848  {
849  // build solution vector of linear system
850  d[0] = key_positions[0][coord] + 2.0 * key_positions[1][coord];
851  for (int i = 1; i < n-1; i++)
852  d[i] = 4.0*key_positions[i][coord] + 2.0*key_positions[i+1][coord];
853  d[n-1] = 8.0*key_positions[n-1][coord] + key_positions[n][coord];
854 
855  // copy coefficients, we are going to reuse them for every coordinate
856  a = a_orig;
857  b = b_orig;
858  c = c_orig;
859 
860  // forward sweep
861  c[0] = c[0]/b[0];
862  d[0] = d[0]/b[0];
863 
864  for (int i = 1; i < n; ++i)
865  {
866  float m = b[i] - a[i]*c[i-1];
867  c[i] = c[i] / m;
868  d[i] = (d[i] - a[i]*d[i-1]) / m;
869  }
870 
871  // back substitution
872  control_points_1[n-1][coord] = d[n-1];
873  for (int i = n-2; i >= 0; --i)
874  {
875  control_points_1[i][coord] = d[i] - c[i]*control_points_1[i+1][coord];
876  }
877  // add one last control point to facilitate future operations (same size as key vector)
878  control_points_1[n][coord] = control_points_1[n-1][coord];
879  }
880 
881  // set w = 1 for all control points
882  for (int i = 0; i <= n; ++i)
883  {
884  control_points_1[i][3] = 1.0;
885  }
886 
887  // control point 2 can be determined directly now
888  Eigen::Vector4f pt;
889  for (int i = 0; i < n-1; ++i)
890  {
891  pt = 2.0* key_positions[i+1] - control_points_1[i+1];
892  control_points_2[i] = pt;
893  }
894  pt = (key_positions[n] + control_points_1[n-1])*0.5;
895  control_points_2[n-1] = pt;
896  control_points_2[n] = pt;
897  }
898 
899 
907  void computeArcLength (void)
908  {
909  float divs = 100.0;
910  Eigen::Vector4f p0;
911  Eigen::Vector4f p1;
912  float dist = 0.0;
913  path_length = 0.0;
914 
915  arc_lengths.clear();
916 
917  p0 = key_positions[0];
918  for (unsigned int seg = 0; seg < key_positions.size()-1; ++seg)
919  {
920  vector <float> seg_lengths;
921 
922  // this is a pause position, just fill with constant length
923  if (key_intervals[seg] > 0.0)
924  {
925  float l = key_intervals[seg] / divs;
926  // already include extra segment since they are all the same
927  for (int i = 0; i < divs+1; ++i)
928  {
929  dist += l;
930  seg_lengths.push_back(dist);
931  }
932  p1 = key_positions[seg+1];
933  }
934  // otherwise divide the curve segment into divs linear segments
935  else
936  {
937  for (int i = 0; i < divs; ++i)
938  {
939  p1 = pointOnSegment( (float)i/divs, seg);
940  dist += (p1-p0).norm();
941 
942  seg_lengths.push_back(dist);
943  p0 = p1;
944  }
945  // to make life easier when converting from t to s,
946  // we also repeat the last sub segment length at the end
947  // even though it will be covered by the first sub segment
948  // of the next Beziér segment
949  // note that we do not increment dist, since it will be done
950  // in the next iteration
951  p1 = key_positions[seg+1];
952  seg_lengths.push_back( dist + (p1-p0).norm() );
953  }
954  arc_lengths.push_back (seg_lengths);
955  }
956  // the last segment connecting to the final key position
957  // there is no segment starting at this key position, so it
958  // must be treated apart
959  p1 = key_positions[key_positions.size()-1];
960  dist += (p1-p0).norm();
961 
962  path_length = dist;
963 
964  // insert a last vector with only the total distance
965  // makes life easier when converting from arc length to time parameter
966  vector <float> last_seg;
967  last_seg.push_back (dist);
968  arc_lengths.push_back(last_seg);
969 
970  }
971 
972  void printDebugInfo (void)
973  {
974  float global_t = anim_time;
975  float t = toLocalParameter (global_t);
976  int segment = curveSegment (global_t);
977 
978  Eigen::Vector4f pt = pointOnSegment(t, segment);
979 
980  Eigen::Quaternionf qt;
981  if (segment >= 0 && key_positions.size() - segment > 2)
982  qt = squad(segment, t);
983  else
984  qt = key_quaternions[segment].slerp(t, key_quaternions[segment+1]);
985 
986  Eigen::Affine3f m = Eigen::Affine3f::Identity();
987  m.rotate(qt);
988  m.translation() = pt.head(3);
989 
990  cout << "quat : (" << qt.w() << " , " << qt.vec().transpose() << " ) " << endl;
991  cout << "t : " << pt.head(3).transpose() << endl;
992  cout << "m : " << endl << m.matrix() << endl << endl;
993  }
994 
995 
996  void writeToFile (const string filename)
997  {
998  ofstream file;
999  file.open (filename.c_str());
1000 
1001  file << key_positions.size() << endl;
1002  for (unsigned int i = 0; i < key_positions.size(); ++i)
1003  {
1004  file << key_positions[i].transpose() << endl;
1005  file << key_quaternions[i].w() << " " << key_quaternions[i].vec().transpose() << endl;
1006  file << key_directions[i].w() << " " << key_directions[i].vec().transpose() << endl;
1007  file << key_intervals[i] << endl;
1008 
1009  }
1010  file.close();
1011  }
1012 
1013  void loadFromFile (const string filename)
1014  {
1015  ifstream file (filename.c_str());
1016 
1017  if (file.is_open())
1018  {
1019  string line;
1020  float elem;
1021  int num;
1022 
1023  Eigen::Quaternion<float> q;
1024  Eigen::Vector4f v;
1025 
1026  getline(file, line);
1027  istringstream iss(line);
1028  iss >> num;
1029 
1030  for (int i = 0; i < num; ++i)
1031  {
1032  // read key position
1033  getline(file, line);
1034  iss.clear();
1035  iss.str(line);
1036  iss >> v[0] >> v[1] >> v[2] >> v[3];
1037  key_positions.push_back(v);
1038 
1039  // read key quaternion
1040  getline(file, line);
1041  iss.clear();
1042  iss.str(line);
1043  iss >> q.w() >> q.vec()[0] >> q.vec()[1] >> q.vec()[2];
1044  key_quaternions.push_back(q);
1045 
1046  // read key direction
1047  getline(file, line);
1048  iss.clear();
1049  iss.str(line);
1050  iss >> q.w() >> q.vec()[0] >> q.vec()[1] >> q.vec()[2];
1051  key_directions.push_back(q);
1052 
1053  // read key interval
1054  getline(file, line);
1055  iss.clear();
1056  iss.str(line);
1057  iss >> elem;
1058  key_intervals.push_back(elem);
1059  }
1060  }
1061  if (key_positions.size() > 1)
1062  {
1063  fillVertexData();
1064  }
1065  }
1066 
1067 };
1068 
1069 }
1070 #endif
float getNearPlane(void) const
Returns near plane value.
Definition: camera.hpp:319
bool loop_animation
Flag to loop animation.
Definition: path.hpp:65
bool draw_control_points
Flag to render control points.
Definition: path.hpp:68
Shader camerapath_shader
Path shader, used for rendering the curve.
Definition: path.hpp:114
void render(const Tucano::Camera &camera, const Tucano::Camera &light)
Renders smooth path End points for each Beziér is passed as line_strip and control points as vertex a...
Definition: path.hpp:245
void loadFromFile(const string filename)
Definition: path.hpp:1013
VertexAttribute * createAttribute(string name, vector< Eigen::Vector4f > &attrib)
Creates and loads a new mesh attribute of 4 floats.
Definition: mesh.hpp:583
void reset(void)
Resets the path.
Definition: path.hpp:136
vector< Eigen::Quaternion< float > > key_quaternions
Rotation state at each key frame.
Definition: path.hpp:92
Eigen::Affine3f * modelMatrix(void)
Returns a pointer to the model matrix.
Definition: model.hpp:112
void getViewMatrix(GLdouble *matrix)
Return the modelview matrix as a GLdouble array.
Definition: camera.hpp:126
A simple sphere shape.
Definition: sphere.hpp:83
bool isAnimating(void)
Returns if Animation is running or not.
Definition: path.hpp:660
void getProjectionMatrix(GLdouble *matrix)
Return the projection matrix as a GLdouble array.
Definition: camera.hpp:142
Definition: bufferobject.hpp:34
float getFarPlane(void) const
Returns far plane value.
Definition: camera.hpp:328
vector< Eigen::Quaternion< float > > control_quaternions
Control quaternions for SQUAD.
Definition: path.hpp:95
void resetAnimation(void)
Resets animation to first key position.
Definition: path.hpp:715
Mesh control_segments
Definition: path.hpp:105
void initialize(void)
Calls all the functions related to the shader initialization, i.e., creates, loads the shaders from t...
Definition: shader.hpp:641
float arcLengthToTime(float s)
Converts from given arc length to time parameter.
Definition: path.hpp:574
Eigen::Quaternionf squad(int seg, float t)
SQUAD - Spherical and Quadrangle quaternion interpolation.
Definition: path.hpp:454
Path class, defines control points and a cubic Bezier approximation for defining a smooth path from k...
Definition: path.hpp:51
void stopAnimation(void)
Stop animation.
Definition: path.hpp:707
void setAnimSpeed(float as)
Sets the animation speed.
Definition: path.hpp:742
A Shader object represents one GLSL program.
Definition: shader.hpp:45
void setColor(const Eigen::Vector4f &color)
Sets the default color of the model.
Definition: model.hpp:65
float path_length
Total path length.
Definition: path.hpp:89
void computeControlQuaternions(void)
Compute control points for SQUAD.
Definition: path.hpp:752
void stepBackward(void)
Move animation backward one step.
Definition: path.hpp:687
void render(const Tucano::Camera &camera, const Tucano::Camera &light)
Render camera representation.
Definition: coordinateaxes.hpp:67
void errorCheckFunc(std::string file, int line, std::string message="")
GL error check method.
Definition: misc.hpp:53
Visual representation of a 3D coordinate axes.
Definition: coordinateaxes.hpp:44
vector< vector< float > > arc_lengths
Arc-length approximation splitting each Beziér segment into linear segments.
Definition: path.hpp:86
void setLoopAnimation(bool f)
Set loop animation flag.
Definition: path.hpp:634
bool animating
Start/stop animation.
Definition: path.hpp:62
int curveSegment(float t)
returns the segment given a time t in [0,1] for the whole path
Definition: path.hpp:349
Eigen::Quaternion< float > directionAtTime(float global_t)
return a direction at a given path parameter
Definition: path.hpp:536
void initialize(string shader_dir="../effects/shaders/")
Initializes shaders.
Definition: path.hpp:161
void addKeyDirection(const Eigen::Quaternion< float > q)
Add an optial key direction Key directions are interpolated via SLERP and not SQUAD This is specially...
Definition: path.hpp:231
vector< Eigen::Vector4f > control_points_1
First control point between two key positions.
Definition: path.hpp:80
void toggleDrawControlPoints(void)
Toggle render control points.
Definition: path.hpp:642
void initOpenGLMatrices(void)
Initializes the view and projection matrices. They are all initialized as Identity matrices...
Definition: path.hpp:151
void stepForward(void)
Move animation forward one step.
Definition: path.hpp:668
vector< Eigen::Vector4f > control_points_2
Second control point between two key positions.
Definition: path.hpp:83
Mesh curve
Definition: path.hpp:102
Eigen::Quaternion< float > directionAtCurrentTime(void)
Return the direction at current animation time.
Definition: path.hpp:564
Eigen::Affine3f cameraAtCurrentTime(void)
Return the view matrix at current animation time.
Definition: path.hpp:555
void startAnimation(void)
Start animation following camera path.
Definition: path.hpp:699
float anim_speed
Movement speed, arc length increment for each animation step.
Definition: path.hpp:56
float animSpeed(void)
Return animation speed where 1 covers the whole curve in one step.
Definition: path.hpp:733
Eigen::Quaternionf logQuaternion(const Eigen::Quaternionf &qi)
Returns the log of a quaternion log(q) q in the form [cos(a), sin(a) v], log(q) = [0...
Definition: path.hpp:402
void computeInnerControlPoints(void)
Compute inner control points from key positions.
Definition: path.hpp:787
void resetModelMatrix(void)
Resets the model matrix.
Definition: model.hpp:159
void unbind(void)
Disables the shader program.
Definition: shader.hpp:1184
Eigen::Affine3f cameraAtTime(float global_t)
return a view matrix at a given path parameter
Definition: path.hpp:500
Eigen::Vector3f getCenter(void) const
Returns the center of the camera in world space.
Definition: camera.hpp:115
Eigen::Vector4f pointOnSegment(float t, int segment)
Returns a point at time t on a given Beziér segment.
Definition: path.hpp:375
void addKeyPosition(const Tucano::Camera &camera, float interval=0.0)
Add key position The camera will pause at this position for given number of steps, default is zero.
Definition: path.hpp:209
void toggleDrawQuaternions(void)
Toggle render control quaternions.
Definition: path.hpp:650
float toLocalParameter(float t)
converts global parameter t to a local t inside a segment
Definition: path.hpp:361
vector< float > key_intervals
Steps to stay paused at a given key position, usually zero.
Definition: path.hpp:77
Eigen::Quaternionf expQuaternion(const Eigen::Quaternionf &q)
Returns the exp of a quaternion exp(q) q in the form [0, a v], exp(q) = [cos(a), sin(a) v] with |v|=1...
Definition: path.hpp:431
Eigen::Vector4f pointOnPath(float global_t)
compute point on path given t in [0,1]
Definition: path.hpp:389
vector< Eigen::Vector4f > key_positions
Camera position at each Key frames.
Definition: path.hpp:74
virtual void unbindBuffers(void)
Unbinds all buffers.
Definition: mesh.hpp:702
void computeArcLength(void)
Compute an approximation of the arclength.
Definition: path.hpp:907
void writeToFile(const string filename)
Definition: path.hpp:996
void loadVertices(vector< Eigen::Vector4f > &vert)
Load vertices (x,y,z,w) and creates appropriate vertex attribute. The default attribute name is "in_P...
Definition: mesh.hpp:312
void load(string name, string shader_dir="")
Loads a shader given a directory and a name. Searches for all shader extensions in directory...
Definition: shader.hpp:436
void bind(void)
Enables the shader program for usage.
Definition: shader.hpp:1176
vector< Eigen::Quaternion< float > > key_directions
Rotation only interpolation (via Slerp) useful for accompaning light direction for example...
Definition: path.hpp:98
void render(const Tucano::Camera &camera, const Tucano::Camera &light)
Render sphere.
Definition: sphere.hpp:115
void fillVertexData(void)
Fill the vertices array.
Definition: path.hpp:173
virtual void bindBuffers(void)
Binds all buffers.
Definition: mesh.hpp:677
#define stringify(x)
Definition: misc.hpp:33
A common Mesh, usually containing triagles or points.
Definition: mesh.hpp:194
Defines an abstract camera with a projection and view matrices.
Definition: camera.hpp:37
void setAttributeLocation(Shader *shader)
Automatically sets the attribute locations for a given Shader.
Definition: mesh.hpp:541
Shapes::CoordinateAxes axes
Coordinate axes for visualizing quaternions at key positions.
Definition: path.hpp:111
Shapes::Sphere sphere
A sphere to visually represent the path&#39;s key positions.
Definition: path.hpp:108
float anim_time
Animation time.
Definition: path.hpp:59
void printDebugInfo(void)
Definition: path.hpp:972
Shader phong_shader
To render simple lines.
Definition: path.hpp:117
Path()
Default constructor.
Definition: path.hpp:124
void toggleAnimation(void)
Toggle animation.
Definition: path.hpp:625
float animTime(void)
Return current animation time.
Definition: path.hpp:724
bool draw_quaternions
Flag to render quaternions at key positions.
Definition: path.hpp:71
void setUniform(GLint location, GLint a, GLint b, GLint c, GLint d)
Sets an uniform integer 4D vector (ivec4) given a location and the vector values. ...
Definition: shader.hpp:1258