MRPT  2.0.4
COpenGLViewport.cpp
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | https://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2020, Individual contributors, see AUTHORS file |
6  | See: https://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See: https://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 
10 #include "opengl-precomp.h" // Precompiled header
11 
12 #include <mrpt/math/TLine3D.h>
13 #include <mrpt/math/geometry.h> // crossProduct3D()
23 #include <Eigen/Dense>
24 
25 #include <mrpt/opengl/opengl_api.h>
26 
27 using namespace mrpt;
28 using namespace mrpt::poses;
29 using namespace mrpt::opengl;
30 using namespace mrpt::math;
32 using namespace std;
33 
35 
36 //#define OPENGLVIEWPORT_ENABLE_TIMEPROFILING
37 
38 #if defined(OPENGLVIEWPORT_ENABLE_TIMEPROFILING)
39 mrpt::system::CTimeLogger glv_timlog;
40 #endif
41 
42 /*--------------------------------------------------------------
43 
44  IMPLEMENTATION OF COpenGLViewport
45 
46  ---------------------------------------------------------------*/
47 
48 /*--------------------------------------------------------------
49  Constructor
50  ---------------------------------------------------------------*/
51 COpenGLViewport::COpenGLViewport(COpenGLScene* parent, const string& name)
52  : m_parent(parent), m_name(name)
53 {
54 }
55 
57 
58 void COpenGLViewport::setCloneView(const string& clonedViewport)
59 {
60  clear();
61  m_isCloned = true;
62  m_clonedViewport = clonedViewport;
63 }
64 
66  const double x, const double y, const double width, const double height)
67 {
69  ASSERT_(m_view_width > 0);
71 
72  m_view_x = x;
73  m_view_y = y;
74  m_view_width = width;
75  m_view_height = height;
76 
77  MRPT_END
78 }
79 
80 /*--------------------------------------------------------------
81  getViewportPosition
82  ---------------------------------------------------------------*/
84  double& x, double& y, double& width, double& height)
85 {
86  x = m_view_x;
87  y = m_view_y;
88  width = m_view_width;
89  height = m_view_height;
90 }
91 
92 /*--------------------------------------------------------------
93  clear
94  ---------------------------------------------------------------*/
95 void COpenGLViewport::clear() { m_objects.clear(); }
96 /*--------------------------------------------------------------
97  insert
98  ---------------------------------------------------------------*/
100 {
101  m_objects.push_back(newObject);
102 }
103 
104 // Maps [0,1] to [0,Len], wrap negative numbers, etc.
105 static int sizeFromRatio(
106  const int startCoord, const double dSize, const int iLength)
107 {
108  if (dSize > 1) // >1 -> absolute pixels:
109  return static_cast<int>(dSize);
110  else if (dSize < 0)
111  { // Negative numbers: Specify the right side coordinates instead of
112  // the width:
113  if (dSize >= -1)
114  return static_cast<int>(-iLength * dSize - startCoord + 1);
115  else
116  return static_cast<int>(-dSize - startCoord + 1);
117  }
118  // Otherwise: a fraction
119  return static_cast<int>(iLength * dSize);
120 }
121 static int startFromRatio(const double frac, const int dSize)
122 {
123  return frac > 1 ? static_cast<int>(frac)
124  : (frac < 0 ? static_cast<int>(dSize + frac)
125  : static_cast<int>(dSize * frac));
126 }
127 
128 // "Image mode" rendering:
130 {
131 #if MRPT_HAS_OPENGL_GLUT
132 #if defined(OPENGLVIEWPORT_ENABLE_TIMEPROFILING)
134  glv_timlog, "COpenGLViewport::render imageview");
135 #endif
136 
137  // Do we have an actual image to render?
138  if (!m_imageview_plane) return;
139 
140  auto _ = m_state;
141 
142  glDisable(GL_DEPTH_TEST);
143  glEnable(GL_BLEND);
144  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
145 
146  // Adjust the aspect ratio:
147  const auto img_w = m_imageview_plane->getTextureImage().getWidth();
148  const auto img_h = m_imageview_plane->getTextureImage().getHeight();
149  const double img_ratio = double(img_w) / img_h;
150  const double vw_ratio = double(_.viewport_width) / _.viewport_height;
151  const double ratio = vw_ratio / img_ratio;
152 
153  _.mv_matrix.setIdentity();
154  _.p_matrix.setIdentity();
155 
156  if (img_ratio > 1)
157  _.p_matrix(1, 1) /= img_ratio;
158  else if (img_ratio > 0)
159  _.p_matrix(0, 0) /= img_ratio;
160 
161  if (ratio > 0) _.p_matrix(0, 0) /= ratio;
162 
163  auto &p00 = _.p_matrix(0, 0), &p11 = _.p_matrix(1, 1);
164  if (p00 > 0 && p11 > 0)
165  {
166  const double s = (p00 > p11) ? p00 : p11;
167  p00 /= s;
168  p11 /= s;
169  }
170 
171  _.pmv_matrix.asEigen() = _.p_matrix.asEigen() * _.mv_matrix.asEigen();
172 
173  // Pass 1: Process all objects (recursively for sets of objects):
174  CListOpenGLObjects lst;
175  lst.push_back(m_imageview_plane);
178 
179  // pass 2: render, sorted by shader program:
181 
182 #endif
183 }
184 
186 
188 {
189 #if MRPT_HAS_OPENGL_GLUT
190  MRPT_START
191 
192  std::vector<shader_id_t> lstShaderIDs = {
196 
197  for (const auto& id : lstShaderIDs)
198  {
200 
201  ASSERT_(m_shaders[id]);
202  ASSERT_(!m_shaders[id]->empty());
203  }
204 
205  MRPT_END
206 #endif
207 }
208 
209 /** Render a normal scene with 3D objects */
211 {
212 #if MRPT_HAS_OPENGL_GLUT
213  MRPT_START
214 
215  // Prepare camera (projection matrix):
216  const CListOpenGLObjects* objectsToRender = nullptr;
217  COpenGLViewport* viewForGetCamera = nullptr;
218 
219  if (m_isCloned)
220  { // Clone: render someone's else objects.
221  ASSERT_(m_parent.get() != nullptr);
222 
223  COpenGLViewport::Ptr view = m_parent->getViewport(m_clonedViewport);
224  if (!view)
226  "Cloned viewport '%s' not found in parent COpenGLScene",
227  m_clonedViewport.c_str());
228 
229  objectsToRender = &view->m_objects;
230  viewForGetCamera =
231  m_isClonedCamera ? view.get() : const_cast<COpenGLViewport*>(this);
232  }
233  else
234  { // Normal case: render our own objects:
235  objectsToRender = &m_objects;
236  viewForGetCamera = const_cast<COpenGLViewport*>(this);
237  }
238 
239  // Get camera:
240  // 1st: if there is a CCamera in the scene (nullptr if no camera found):
241  const CCamera* myCamera =
242  dynamic_cast<CCamera*>(viewForGetCamera->getByClass<CCamera>().get());
243 
244  // 2nd: the internal camera of all viewports:
245  if (!myCamera) myCamera = &viewForGetCamera->m_camera;
246 
248 
249  auto& _ = m_state;
250 
251  _.is_projective = myCamera->m_projectiveModel;
252  _.FOV = myCamera->m_projectiveFOVdeg;
253  _.eyeDistance = myCamera->m_eyeDistance;
254  _.azimuth = DEG2RAD(myCamera->m_azimuthDeg);
255  _.elev = DEG2RAD(myCamera->m_elevationDeg);
256 
257  if (myCamera->is6DOFMode())
258  {
259  // In 6DOFMode eye is set viewing towards the direction of the
260  // positive Z axis
261  // Up is set as Y axis
262  mrpt::poses::CPose3D viewDirection, pose, at;
263  viewDirection.x(+1);
264  pose = mrpt::poses::CPose3D(myCamera->getPose());
265  at = pose + viewDirection;
266 
267  _.eye.x = pose.x();
268  _.eye.y = pose.y();
269  _.eye.z = pose.z();
270  _.pointing.x = at.x();
271  _.pointing.y = at.y();
272  _.pointing.z = at.z();
273  _.up.x = pose.getRotationMatrix()(0, 2);
274  _.up.y = pose.getRotationMatrix()(1, 2);
275  _.up.z = pose.getRotationMatrix()(2, 2);
276  }
277  else
278  {
279  // Normal mode: use "camera orbit" parameters to compute pointing-to
280  // point:
281  const double dis = std::max<double>(0.005, myCamera->m_eyeDistance);
282  _.eye.x = _.pointing.x + dis * cos(_.azimuth) * cos(_.elev);
283  _.eye.y = _.pointing.y + dis * sin(_.azimuth) * cos(_.elev);
284  _.eye.z = _.pointing.z + dis * sin(_.elev);
285 
286  _.pointing.x = myCamera->m_pointingX;
287  _.pointing.y = myCamera->m_pointingY;
288  _.pointing.z = myCamera->m_pointingZ;
289 
290  _.up.x = -cos(_.azimuth) * sin(_.elev);
291  _.up.y = -sin(_.azimuth) * sin(_.elev);
292  _.up.z = cos(_.elev);
293  }
294 
295  // Compute the projection matrix (p_matrix):
296  _.computeProjectionMatrix(m_clip_min, m_clip_max);
297 
298  // Apply eye center and lookAt to p_matrix:
299  _.applyLookAt();
300 
301  // Optional pre-Render user code:
302  if (hasSubscribers())
303  {
304  mrptEventGLPreRender ev(this);
305  this->publishEvent(ev);
306  }
307 
308  // Global OpenGL settings:
309  // ---------------------------------
310  glHint(
311  GL_POLYGON_SMOOTH_HINT,
312  m_OpenGL_enablePolygonNicest ? GL_NICEST : GL_FASTEST);
313  CHECK_OPENGL_ERROR();
314 
315  // Reset model-view 4x4 matrix to the identity transformation:
316  _.mv_matrix.setIdentity();
317 
318  glEnable(GL_DEPTH_TEST);
319  glDepthFunc(GL_LEQUAL); // GL_LESS
320 
321  glEnable(GL_BLEND);
322  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
323 
324 // Enable point sizes>1
325 #if defined(GL_PROGRAM_POINT_SIZE) // it seems it's undefined in OSX (?)
326  glEnable(GL_PROGRAM_POINT_SIZE);
327  CHECK_OPENGL_ERROR();
328 #endif
329 
330  // Pass 1: Process all objects (recursively for sets of objects):
332  mrpt::opengl::enqueForRendering(*objectsToRender, _, rq);
333 
334  // pass 2: render, sorted by shader program:
336 
337  MRPT_END
338 
339 #endif
340 }
341 
343 {
344 #if MRPT_HAS_OPENGL_GLUT
345  MRPT_START
346  if (m_borderWidth < 1) return;
347 
348  auto _ = m_state;
349 
351  _.p_matrix.setIdentity();
352  _.pmv_matrix.setIdentity();
353 
354  glDisable(GL_DEPTH_TEST);
355  glEnable(GL_BLEND);
356  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
357 
358  //
359  if (!m_borderLines)
360  {
362  m_borderLines->appendLine(-1, -1, 0, -1, 1, 0);
363  m_borderLines->appendLine(-1, 1, 0, 1, 1, 0);
364  m_borderLines->appendLine(1, 1, 0, 1, -1, 0);
365  m_borderLines->appendLine(1, -1, 0, -1, -1, 0);
366  }
367  m_borderLines->setLineWidth(m_borderWidth);
368  m_borderLines->setColor_u8(m_borderColor);
369 
370  CListOpenGLObjects lst;
371  lst.push_back(m_borderLines);
372 
373  // Pass 1: Process all objects (recursively for sets of objects):
376 
377  // pass 2: render, sorted by shader program:
379  MRPT_END
380 #endif
381 }
382 
384 {
385 #if MRPT_HAS_OPENGL_GLUT
386  MRPT_START
387 
388  // Ensure GL objects are up-to-date:
390 
391  // Prepare shaders upon first invokation:
392  if (m_shaders.empty()) loadDefaultShaders();
393 
394  // Prepare camera (projection matrix):
395  TRenderMatrices _ = m_state; // make a copy
396 
397  // Compute the projection matrix (p_matrix):
398  // was: glLoadIdentity(); glOrtho(0, w, 0, h, -1, 1);
399  const auto w = _.viewport_width, h = _.viewport_height;
400  _.is_projective = false;
401 
402  _.p_matrix.setIdentity();
403  //_.computeOrthoProjectionMatrix(0, w, 0, h, m_clip_min, m_clip_max);
404 
405  // Reset model-view 4x4 matrix to the identity transformation:
407 
408  // glDisable(GL_DEPTH_TEST);
409  glEnable(GL_BLEND);
410  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
411 
412  // Collect all 2D text objects, and update their properties:
413  CListOpenGLObjects objs;
414  for (auto& kv : m_2D_texts.messages)
415  {
416  const DataPerText& label = kv.second;
417 
418  // If (x,y) \in [0,1[, it's interpreted as a ratio, otherwise, as an
419  // actual coordinate in pixels
420  float x =
421  label.x >= 1 ? label.x : (label.x < 0 ? w + label.x : label.x * w);
422  float y =
423  label.y >= 1 ? label.y : (label.y < 0 ? h + label.y : label.y * h);
424 
425  if (CText::Ptr& o = label.gl_text; o)
426  {
427  o->setFont(label.vfont_name, label.vfont_scale * 2);
428  o->setString(label.text);
429  o->setColor(label.color);
430  // Change coordinates: mrpt text (0,0)-(1,1) to OpenGL
431  // (-1,-1)-(+1,+1):
432  o->setLocation(-1.0f + 2 * x / w, -1.0f + 2 * y / h, 0);
433  objs.push_back(o);
434  }
435  if (CText::Ptr& o = label.gl_text_shadow; o)
436  {
437  o->setFont(label.vfont_name, label.vfont_scale * 2);
438  o->setString(label.text);
439  o->setColor(label.shadow_color);
440  // Change coordinates: mrpt text (0,0)-(1,1) to OpenGL
441  // (-1,-1)-(+1,+1):
442  o->setLocation(
443  -1.0f + 2 * (x + 1) / w, -1.0f + 2 * (y - 1) / h, 0.1);
444  objs.push_back(o);
445  }
446  }
447 
448  // Pass 1: Process all objects (recursively for sets of objects):
450  mrpt::opengl::enqueForRendering(objs, _, rq);
451 
452  // pass 2: render, sorted by shader program:
454  MRPT_END
455 #endif
456 }
457 
459  [[maybe_unused]] const int render_width,
460  [[maybe_unused]] const int render_height,
461  [[maybe_unused]] const int render_offset_x,
462  [[maybe_unused]] const int render_offset_y) const
463 {
464 #if MRPT_HAS_OPENGL_GLUT
465  MRPT_START
466 
467  // Change viewport:
468  // -------------------------------------------
469  const GLint vx = render_offset_x + startFromRatio(m_view_x, render_width);
470  const GLint vy = render_offset_y + startFromRatio(m_view_y, render_height);
471  const GLint vw = sizeFromRatio(vx, m_view_width, render_width);
472  const GLint vh = sizeFromRatio(vy, m_view_height, render_height);
473 
474  glViewport(vx, vy, vw, vh);
475  CHECK_OPENGL_ERROR();
476 
477  // Clear depth&/color buffers:
478  // -------------------------------------------
479  m_state.viewport_width = vw;
481 
482  glScissor(vx, vy, vw, vh);
483  CHECK_OPENGL_ERROR();
484 
485  glEnable(GL_SCISSOR_TEST);
486  CHECK_OPENGL_ERROR();
487 
488  if (!m_isTransparent)
489  { // Clear color & depth buffers:
490  // Save?
491 
492  GLclampf prevCol[4];
494  {
495  glGetFloatv(GL_COLOR_CLEAR_VALUE, prevCol);
496  CHECK_OPENGL_ERROR();
497  glClearColor(
500  CHECK_OPENGL_ERROR();
501  }
502 
503  glClear(
504  GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
505  CHECK_OPENGL_ERROR();
506 
507  // Restore old colors:
509  {
510  glClearColor(prevCol[0], prevCol[1], prevCol[2], prevCol[3]);
511  CHECK_OPENGL_ERROR();
512  }
513  }
514  else
515  { // Clear depth buffer only:
516  glClear(GL_DEPTH_BUFFER_BIT);
517  CHECK_OPENGL_ERROR();
518  }
519  glDisable(GL_SCISSOR_TEST);
520  CHECK_OPENGL_ERROR();
521 
522  // Prepare shaders upon first invokation:
523  if (m_shaders.empty()) loadDefaultShaders();
524 
525  // If we are in "image mode", rendering is much simpler: just set
526  // ortho projection and render the image quad:
527  if (m_isImageView)
528  renderImageMode();
529  else
531 
532  // Draw text messages, if any:
534 
535  // Finally, draw the border:
537 
538  // Optional post-Render user code:
539  if (hasSubscribers())
540  {
541  mrptEventGLPostRender ev(this);
542  this->publishEvent(ev);
543  }
544 
545  MRPT_END
546 #else
548  "The MRPT has been compiled with MRPT_HAS_OPENGL_GLUT=0! OpenGL "
549  "functions are not implemented");
550 #endif
551 }
552 
553 uint8_t COpenGLViewport::serializeGetVersion() const { return 4; }
555 {
556  // Save data:
560 
561  // Added in v1:
564 
565  // Save objects:
566  uint32_t n;
567  n = (uint32_t)m_objects.size();
568  out << n;
569  for (const auto& m_object : m_objects) out << *m_object;
570 
571  // Added in v2: Global OpenGL settings:
573 
574  // Added in v3: Lights
575  out << m_lights;
576 
577  // Added in v4: text messages:
578  out.WriteAs<uint32_t>(m_2D_texts.messages.size());
579  for (auto& kv : m_2D_texts.messages)
580  {
581  out << kv.first; // id
582  out << kv.second.x << kv.second.y << kv.second.text;
583 
584  const auto& fp = kv.second;
585 
586  out << fp.vfont_name << fp.vfont_scale << fp.color << fp.draw_shadow
587  << fp.shadow_color << fp.vfont_spacing << fp.vfont_kerning;
588  out.WriteAs<uint8_t>(static_cast<uint8_t>(fp.vfont_style));
589  }
590 }
591 
593  mrpt::serialization::CArchive& in, uint8_t version)
594 {
595  switch (version)
596  {
597  case 0:
598  case 1:
599  case 2:
600  case 3:
601  case 4:
602  {
603  // Load data:
604  in >> m_camera >> m_isCloned >> m_isClonedCamera >>
608 
609  // in v1:
610  if (version >= 1)
611  {
615  }
616  else
617  {
618  m_custom_backgb_color = false;
619  }
620 
621  // Load objects:
622  uint32_t n;
623  in >> n;
624  clear();
625  m_objects.resize(n);
626 
627  for_each(
628  m_objects.begin(), m_objects.end(), ObjectReadFromStream(&in));
629 
630  // Added in v2: Global OpenGL settings:
631  if (version >= 2)
632  {
634  }
635  else
636  {
637  // Defaults
638  }
639 
640  // Added in v3: Lights
641  if (version >= 3)
642  in >> m_lights;
643  else
644  {
645  // Default:
647  }
648 
649  // v4: text:
650  m_2D_texts.messages.clear();
651  uint32_t nTexts = 0;
652  if (version >= 4) nTexts = in.ReadAs<uint32_t>();
653 
654  for (uint32_t i = 0; i < nTexts; i++)
655  {
656  const auto id = in.ReadAs<uint32_t>();
657  double x, y;
658  std::string text;
659  in >> x >> y >> text;
660 
661  TFontParams fp;
662 
663  in >> fp.vfont_name >> fp.vfont_scale >> fp.color >>
664  fp.draw_shadow >> fp.shadow_color >> fp.vfont_spacing >>
665  fp.vfont_kerning;
666  fp.vfont_style =
667  static_cast<TOpenGLFontStyle>(in.ReadAs<uint8_t>());
668 
669  this->addTextMessage(x, y, text, id, fp);
670  }
671  }
672  break;
673  default:
675  };
676 }
677 
678 /*---------------------------------------------------------------
679  getByName
680  ---------------------------------------------------------------*/
682 {
683  for (auto& m_object : m_objects)
684  {
685  if (m_object->m_name == str)
686  return m_object;
687  else if (
688  m_object->GetRuntimeClass() ==
690  {
691  CRenderizable::Ptr ret =
692  std::dynamic_pointer_cast<CSetOfObjects>(m_object)->getByName(
693  str);
694  if (ret) return ret;
695  }
696  }
697  return CRenderizable::Ptr();
698 }
699 
701 {
702  for (auto& obj : m_objects) obj->initializeTextures();
703 }
704 
705 void COpenGLViewport::dumpListOfObjects(std::vector<std::string>& lst)
706 {
707  for (auto& m_object : m_objects)
708  {
709  // Single obj:
710  string s(m_object->GetRuntimeClass()->className);
711  if (m_object->m_name.size())
712  s += string(" (") + m_object->m_name + string(")");
713  lst.emplace_back(s);
714 
715  if (m_object->GetRuntimeClass() ==
717  {
718  std::vector<std::string> auxLst;
719 
720  dynamic_cast<CSetOfObjects*>(m_object.get())
721  ->dumpListOfObjects(auxLst);
722 
723  for (const auto& i : auxLst) lst.emplace_back(string(" ") + i);
724  }
725  }
726 }
727 
728 /*--------------------------------------------------------------
729  removeObject
730  ---------------------------------------------------------------*/
732 {
733  for (auto it = m_objects.begin(); it != m_objects.end(); ++it)
734  if (*it == obj)
735  {
736  m_objects.erase(it);
737  return;
738  }
739  else if (
740  (*it)->GetRuntimeClass() ==
742  dynamic_cast<CSetOfObjects*>(it->get())->removeObject(obj);
743 }
744 
746  const float clip_min, const float clip_max)
747 {
748  ASSERT_ABOVE_(clip_max, clip_min);
749 
750  m_clip_min = clip_min;
751  m_clip_max = clip_max;
752 }
753 
755  float& clip_min, float& clip_max) const
756 {
757  clip_min = m_clip_min;
758  clip_max = m_clip_max;
759 }
760 
761 /*--------------------------------------------------------------
762  get3DRayForPixelCoord
763  ---------------------------------------------------------------*/
765  const double x_coord, const double y_coord, mrpt::math::TLine3D& out_ray,
766  mrpt::poses::CPose3D* out_cameraPose) const
767 {
769 
770  const double ASPECT =
772 
773  // unitary vector between (eye) -> (pointing):
774  TPoint3D pointing_dir;
775  pointing_dir.x = -cos(m_state.azimuth) * cos(m_state.elev);
776  pointing_dir.y = -sin(m_state.azimuth) * cos(m_state.elev);
777  pointing_dir.z = -sin(m_state.elev);
778 
779  // The camera X vector (in 3D) can be computed from the camera azimuth
780  // angle:
781  TPoint3D cam_x_3d;
782  cam_x_3d.x = -sin(m_state.azimuth);
783  cam_x_3d.y = cos(m_state.azimuth);
784  cam_x_3d.z = 0;
785 
786  // The camera real UP vector (in 3D) is the cross product:
787  // X3d x pointing_dir:
788  TPoint3D cam_up_3d;
789  mrpt::math::crossProduct3D(cam_x_3d, pointing_dir, cam_up_3d);
790 
791  if (!m_state.is_projective)
792  {
793  // Ortho projection:
794  // -------------------------------
795  double Ax = m_state.eyeDistance * 0.5;
796  double Ay = Ax;
797 
798  if (ASPECT > 1)
799  Ax *= ASPECT;
800  else
801  {
802  if (ASPECT != 0) Ay /= ASPECT;
803  }
804 
805  const double point_lx =
806  (-0.5 + x_coord / m_state.viewport_width) * 2 * Ax;
807  const double point_ly =
808  -(-0.5 + y_coord / m_state.viewport_height) * 2 * Ay;
809 
810  const TPoint3D ray_origin(
811  m_state.eye.x + point_lx * cam_x_3d.x + point_ly * cam_up_3d.x,
812  m_state.eye.y + point_lx * cam_x_3d.y + point_ly * cam_up_3d.y,
813  m_state.eye.z + point_lx * cam_x_3d.z + point_ly * cam_up_3d.z);
814 
815  out_ray.pBase = ray_origin;
816  out_ray.director[0] = pointing_dir.x;
817  out_ray.director[1] = pointing_dir.y;
818  out_ray.director[2] = pointing_dir.z;
819  }
820  else
821  {
822  // Perspective camera
823  // -------------------------------
824 
825  // JL: This can be derived from:
826  // http://www.opengl.org/sdk/docs/man/xhtml/gluPerspective.xml
827  // where one arrives to:
828  // tan(FOVx/2) = ASPECT_RATIO * tan(FOVy/2)
829  //
830  const double FOVy = DEG2RAD(m_state.FOV);
831  const double FOVx = 2.0 * atan(ASPECT * tan(FOVy * 0.5));
832 
833  const auto vw = m_state.viewport_width;
834  const auto vh = m_state.viewport_height;
835  const double len_horz = 2.0 * (-0.5 + x_coord / vw) * tan(0.5 * FOVx);
836  const double len_vert = -2.0 * (-0.5 + y_coord / vh) * tan(0.5 * FOVy);
837  // Point in camera local reference frame
838  const auto l = mrpt::math::TPoint3D(len_horz, len_vert, 1.0);
839 
840  const mrpt::math::TPoint3D ray_director(
841  l.x * cam_x_3d.x + l.y * cam_up_3d.x + l.z * pointing_dir.x,
842  l.x * cam_x_3d.y + l.y * cam_up_3d.y + l.z * pointing_dir.y,
843  l.x * cam_x_3d.z + l.y * cam_up_3d.z + l.z * pointing_dir.z);
844 
845  // Set out ray:
846  out_ray.pBase = m_state.eye;
847  out_ray.director[0] = ray_director.x;
848  out_ray.director[1] = ray_director.y;
849  out_ray.director[2] = ray_director.z;
850 
851  } // end projective
852 
853  // Camera pose:
854  if (out_cameraPose)
855  {
857  M(0, 0) = cam_x_3d.x;
858  M(1, 0) = cam_x_3d.y;
859  M(2, 0) = cam_x_3d.z;
860  M(3, 0) = 0;
861 
862  M(0, 1) = cam_up_3d.x;
863  M(1, 1) = cam_up_3d.y;
864  M(2, 1) = cam_up_3d.z;
865  M(3, 1) = 0;
866 
867  M(0, 2) = pointing_dir.x;
868  M(1, 2) = pointing_dir.y;
869  M(2, 2) = pointing_dir.z;
870  M(3, 2) = 0;
871 
872  M(0, 3) = m_state.eye.x;
873  M(1, 3) = m_state.eye.y;
874  M(2, 3) = m_state.eye.z;
875  M(3, 3) = 1;
876 
877  *out_cameraPose = CPose3D(M);
878  }
879 }
880 
882 {
883  m_camera.set6DOFMode(true);
884  m_camera.setPose(p);
885 }
886 
888  mrpt::poses::CPose3D& out_cameraPose) const
889 {
891  get3DRayForPixelCoord(0, 0, dum, &out_cameraPose);
892 }
893 
894 /** Resets the viewport to a normal 3D viewport \sa setCloneView, setImageView
895  */
897 {
898  // If this was a m_isImageView, remove the quad object:
899  m_imageview_plane.reset();
900 
901  m_isCloned = false;
902  m_isClonedCamera = false;
903  m_isImageView = false;
904 }
905 
907 {
909  m_imageview_plane->assignImage(img);
910 }
912 {
914  m_imageview_plane->assignImage(img);
915 }
916 
918 {
919  // If this is the first time, we have to create the quad object:
920  if (!m_imageview_plane)
921  {
923  // Flip vertically:
924  m_imageview_plane->setPlaneCorners(-1, 1, 1, -1);
925  }
926  m_isImageView = true;
927 }
928 
929 /** Evaluates the bounding box of this object (including possible children) in
930  * the coordinate frame of the object parent. */
933 {
934  bb_min = TPoint3D(
935  std::numeric_limits<double>::max(), std::numeric_limits<double>::max(),
936  std::numeric_limits<double>::max());
937  bb_max = TPoint3D(
938  -std::numeric_limits<double>::max(),
939  -std::numeric_limits<double>::max(),
940  -std::numeric_limits<double>::max());
941 
942  for (const auto& m_object : m_objects)
943  {
944  TPoint3D child_bbmin(
945  std::numeric_limits<double>::max(),
946  std::numeric_limits<double>::max(),
947  std::numeric_limits<double>::max());
948  TPoint3D child_bbmax(
949  -std::numeric_limits<double>::max(),
950  -std::numeric_limits<double>::max(),
951  -std::numeric_limits<double>::max());
952  m_object->getBoundingBox(child_bbmin, child_bbmax);
953 
954  keep_min(bb_min.x, child_bbmin.x);
955  keep_min(bb_min.y, child_bbmin.y);
956  keep_min(bb_min.z, child_bbmin.z);
957 
958  keep_max(bb_max.x, child_bbmax.x);
959  keep_max(bb_max.y, child_bbmax.y);
960  keep_max(bb_max.z, child_bbmax.z);
961  }
962 }
float m_projectiveFOVdeg
Field-of-View in degs, only when projectiveModel=true (default=30 deg).
Definition: CCamera.h:115
void serializeFrom(mrpt::serialization::CArchive &in, uint8_t serial_version) override
Pure virtual method for reading (deserializing) from an abstract archive.
static int startFromRatio(const double frac, const int dSize)
float m_clip_min
The min/max clip depth distances (default: 0.1 - 10000)
An object for reading objects from a stream, intended for being used in STL algorithms.
opengl::CListOpenGLObjects m_objects
The list of objects that comprise the 3D scene.
void serializeTo(mrpt::serialization::CArchive &out) const override
Pure virtual method for writing (serializing) to an abstract archive.
void keep_min(T &var, const K test_val)
If the second argument is below the first one, set the first argument to this lower value...
static Ptr Create(Args &&... args)
A compile-time fixed-size numeric matrix container.
Definition: CMatrixFixed.h:33
CRenderizable::Ptr getByName(const std::string &str)
Returns the first object with a given name, or nullptr if not found.
void get3DRayForPixelCoord(const double x_coord, const double y_coord, mrpt::math::TLine3D &out_ray, mrpt::poses::CPose3D *out_cameraPose=nullptr) const
Compute the 3D ray corresponding to a given pixel; this can be used to allow the user to pick and sel...
#define MRPT_START
Definition: exceptions.h:241
bool m_isTransparent
Whether to clear color buffer.
static constexpr shader_id_t TEXTURED_TRIANGLES
mrpt::opengl::CTexturedPlane::Ptr m_imageview_plane
The image to display, after calling setImageView()
A set of object, which are referenced to the coordinates framework established in this object...
Definition: CSetOfObjects.h:26
#define THROW_EXCEPTION(msg)
Definition: exceptions.h:67
uint32_t m_borderWidth
Default=0, the border around the viewport.
A safe way to call enter() and leave() of a mrpt::system::CTimeLogger upon construction and destructi...
void setCloneView(const std::string &clonedViewport)
Set this viewport as a clone of some other viewport, given its name - as a side effect, current list of internal OpenGL objects is cleared.
void setViewportClipDistances(const float clip_min, const float clip_max)
Set the min/max clip depth distances of the rendering frustum (default: 0.1 - 10000) ...
#define IMPLEMENTS_SERIALIZABLE(class_name, base, NameSpace)
To be added to all CSerializable-classes implementation files.
std::deque< CRenderizable::Ptr > CListOpenGLObjects
A list of smart pointers to renderizable objects.
A description of a bitmapped or vectorized text font.
Definition: opengl_fonts.h:36
void set6DOFMode(bool v)
Set 6DOFMode, if enabled camera is set according to its pose (default=false).
Definition: CCamera.h:80
void processRenderQueue(const RenderQueue &rq, std::map< shader_id_t, mrpt::opengl::Program::Ptr > &shaders, const mrpt::opengl::TLightParameters &lights)
After enqueForRendering(), actually executes the rendering tasks, grouped shader by shader...
void setImageView(const mrpt::img::CImage &img)
Set this viewport into "image view"-mode, where an image is efficiently drawn (fitting the viewport a...
void renderImageMode() const
Render in image mode.
std::shared_ptr< CRenderizable > Ptr
Definition: CRenderizable.h:50
static constexpr shader_id_t TEXT
TPoint3D pBase
Base point.
Definition: TLine3D.h:47
STL namespace.
A viewport within a COpenGLScene, containing a set of OpenGL objects to render.
void getViewportClipDistances(float &clip_min, float &clip_max) const
Get the current min/max clip depth distances of the rendering frustum (default: 0.1 - 10000)
mrpt::safe_ptr< COpenGLScene > m_parent
The scene that contains this viewport.
TRenderMatrices m_state
Info updated with each "render()" and used in "get3DRayForPixelCoord".
void loadDefaultShaders() const
Load all MPRT predefined shader programs into m_shaders.
void crossProduct3D(const T &v0, const U &v1, V &vOut)
Computes the cross product of two 3D vectors, returning a vector normal to both.
Definition: geometry.h:765
std::string vfont_name
Vectorized font name ("sans","mono","serif")
Definition: opengl_fonts.h:41
#define MRPT_THROW_UNKNOWN_SERIALIZATION_VERSION(__V)
For use in CSerializable implementations.
Definition: exceptions.h:97
bool m_isClonedCamera
Set by setCloneCamera.
#define ASSERT_(f)
Defines an assertion mechanism.
Definition: exceptions.h:120
This base provides a set of functions for maths stuff.
bool m_isImageView
Set by setImageView.
void getBoundingBox(mrpt::math::TPoint3D &bb_min, mrpt::math::TPoint3D &bb_max) const
Evaluates the bounding box of this object (including possible children) in the coordinate frame of th...
void addTextMessage(const double x_frac, const double y_frac, const std::string &text, const size_t unique_index=0, const TFontParams &fontParams=TFontParams())
Add 2D text messages overlapped to the 3D rendered scene.
void enqueForRendering(const mrpt::opengl::CListOpenGLObjects &objs, const mrpt::opengl::TRenderMatrices &state, RenderQueue &rq)
Processes, recursively, all objects in the list, classifying them by shader programs into a list suit...
Definition: RenderQueue.cpp:28
static int sizeFromRatio(const int startCoord, const double dSize, const int iLength)
constexpr double DEG2RAD(const double x)
Degrees to radians.
STORED_TYPE ReadAs()
De-serialize a variable and returns it by value.
Definition: CArchive.h:155
static constexpr shader_id_t WIREFRAME
TOpenGLFontStyle
Different style for vectorized font rendering.
Definition: opengl_fonts.h:19
void render(const int render_width, const int render_height, const int render_offset_x=0, const int render_offset_y=0) const
Render the objects in this viewport (called from COpenGLScene)
~COpenGLViewport() override
Destructor: clears all objects.
void unloadShaders()
Unload shader programs in m_shaders.
double vfont_kerning
(default: 0.1) Refer to mrpt::opengl::gl_utils::glDrawText
Definition: opengl_fonts.h:58
void removeObject(const CRenderizable::Ptr &obj)
Removes the given object from the scene (it also deletes the object to free its memory).
TVector3D director
Director vector.
Definition: TLine3D.h:49
TPoint3D_< double > TPoint3D
Lightweight 3D point.
Definition: TPoint3D.h:268
double x() const
Common members of all points & poses classes.
Definition: CPoseOrPoint.h:143
void setNormalMode()
Resets the viewport to a normal 3D viewport.
mrpt::math::CMatrixFloat44 mv_matrix
Model-view matrix.
Rendering state related to the projection and model-view matrices.
void getCurrentCameraPose(mrpt::poses::CPose3D &out_cameraPose) const
Compute the current 3D camera pose.
Classes for 2D/3D geometry representation, both of single values and probability density distribution...
double azimuth
Camera elev & azimuth, in radians.
static constexpr shader_id_t TRIANGLES
void renderTextMessages() const
Renders all messages in the underlying class CTextMessageCapable.
void keep_max(T &var, const K test_val)
If the second argument is above the first one, set the first argument to this higher value...
#define CLASS_ID_NAMESPACE(class_name, namespaceName)
Definition: CObject.h:105
T x
X,Y,Z coordinates.
Definition: TPoint3D.h:29
std::map< shader_id_t, mrpt::opengl::Program::Ptr > m_shaders
Default shader program.
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
bool m_projectiveModel
If set to true (default), camera model is projective, otherwise, it&#39;s orthogonal. ...
Definition: CCamera.h:112
Virtual base class for "archives": classes abstracting I/O streams.
Definition: CArchive.h:54
void clear()
Delete all internal obejcts.
size_t viewport_width
In pixels.
mrpt::math::TPoint3D eye
The camera is here.
An event sent by an mrpt::opengl::COpenGLViewport just after clearing the viewport and setting the GL...
double vfont_spacing
(default: 1.5) Refer to mrpt::opengl::gl_utils::glDrawText
Definition: opengl_fonts.h:55
A versatile "profiler" that logs the time spent within each pair of calls to enter(X)-leave(X), among other stats.
void regenerateGLobjects() const
(re)generate all CText objects in the gl_text fields
A class used to store a 3D pose (a 3D translation + a rotation in 3D).
Definition: CPose3D.h:85
mrpt::vision::TStereoCalibResults out
uint8_t serializeGetVersion() const override
Must return the current versioning number of the object.
#define ASSERTDEB_(f)
Defines an assertion mechanism - only when compiled in debug.
Definition: exceptions.h:190
void initializeTextures()
Initializes all textures in the scene (See opengl::CTexturedPlane::initializeTextures) ...
Program::Ptr LoadDefaultShader(const shader_id_t id)
Loads a set of OpenGL Vertex+Fragment shaders from the default library available in mrpt::opengl...
An event sent by an mrpt::opengl::COpenGLViewport after calling the scene OpenGL drawing primitives a...
#define ASSERT_ABOVE_(__A, __B)
Definition: exceptions.h:155
#define MRPT_END
Definition: exceptions.h:245
void publishEvent(const mrptEvent &e) const
Called when you want this object to emit an event to all the observers currently subscribed to this o...
Definition: CObservable.cpp:57
bool hasSubscribers() const
Can be called by a derived class before preparing an event for publishing with publishEvent to determ...
Definition: CObservable.h:53
mrpt::opengl::CSetOfLines::Ptr m_borderLines
The namespace for 3D scene representation and rendering.
Definition: CGlCanvasBase.h:13
This class allows the user to create, load, save, and render 3D scenes using OpenGL primitives...
Definition: COpenGLScene.h:56
const auto bb_max
std::string m_clonedViewport
Only if m_isCloned=true.
CRenderizable & setPose(const mrpt::poses::CPose3D &o)
Set the 3D pose from a mrpt::poses::CPose3D object (return a ref to this)
mrpt::img::TColorf m_background_color
used only if m_custom_backgb_color
void renderNormalSceneMode() const
Render a normal scene with 3D objects.
mrpt::img::TColorf color
Definition: opengl_fonts.h:46
const auto bb_min
double FOV
Vertical FOV in degrees.
mrpt::math::CMatrixFloat44 p_matrix
Projection matrix, computed by renderNormalScene() from all the parameters above. ...
void getRotationMatrix(mrpt::math::CMatrixDouble33 &ROT) const
Get the 3x3 rotation matrix.
Definition: CPose3D.h:225
A camera: if added to a scene, the viewpoint defined by this camera will be used instead of the camer...
Definition: CCamera.h:33
void renderViewportBorder() const
Render the viewport border, if enabled.
#define THROW_EXCEPTION_FMT(_FORMAT_STRING,...)
Definition: exceptions.h:69
void setViewportPosition(const double x, const double y, const double width, const double height)
Change the viewport position and dimension on the rendering window.
void dumpListOfObjects(std::vector< std::string > &lst)
Retrieves a list of all objects in text form.
mrpt::math::TPose3D getPose() const
Returns the 3D pose of the object as TPose3D.
bool is6DOFMode() const
Definition: CCamera.h:83
void getViewportPosition(double &x, double &y, double &width, double &height)
Get the current viewport position and dimension on the rendering window.
void insert(const CRenderizable::Ptr &newObject)
Insert a new object into the list.
T::Ptr getByClass(size_t ith=0) const
Returns the i&#39;th object of a given class (or of a descendant class), or nullptr (an empty smart point...
double m_view_x
The viewport position [0,1].
Lighting parameters, mostly for triangle shaders.
mrpt::img::TColorf shadow_color
Definition: opengl_fonts.h:49
static Ptr Create(Args &&... args)
Definition: CSetOfLines.h:35
void setCurrentCameraFromPose(mrpt::poses::CPose3D &p)
Changes the point of view of the camera, from a given pose.
static constexpr shader_id_t POINTS
opengl::CCamera m_camera
The camera associated to the viewport.
std::string m_name
The viewport&#39;s name.
A class for storing images as grayscale or RGB bitmaps.
Definition: img/CImage.h:148
float vfont_scale
Size of characters [pixels].
Definition: opengl_fonts.h:44
bool is_projective
true: projective, false: ortho
std::map< shader_id_t, std::multimap< float, RenderQueueElement > > RenderQueue
A queue for rendering, sorted by shader program to minimize changes of OpenGL shader programs while r...
Definition: RenderQueue.h:46
bool m_isCloned
Set by setCloneView.
3D line, represented by a base point and a director vector.
Definition: TLine3D.h:19
TOpenGLFontStyle vfont_style
(default: FILL) See TOpenGLFontStyle.
Definition: opengl_fonts.h:52



Page generated by Doxygen 1.8.14 for MRPT 2.0.4 Git: 33de1d0ad Sat Jun 20 11:02:42 2020 +0200 at sáb jun 20 17:35:17 CEST 2020