iLab Neuromorphic Robotics Toolkit  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ShapeRendererBasic.H
Go to the documentation of this file.
1 /*! @file
2  @author Laurent Itti
3  @copyright GNU Public License (GPL v3)
4  @section License
5  @verbatim
6  // ////////////////////////////////////////////////////////////////////////
7  // The iLab Neuromorphic Robotics Toolkit (NRT) //
8  // Copyright 2010-2012 by the University of Southern California (USC) //
9  // and the iLab at USC. //
10  // //
11  // iLab - University of Southern California //
12  // Hedco Neurociences Building, Room HNB-10 //
13  // Los Angeles, Ca 90089-2520 - USA //
14  // //
15  // See http://ilab.usc.edu for information about this project. //
16  // ////////////////////////////////////////////////////////////////////////
17  // This file is part of The iLab Neuromorphic Robotics Toolkit. //
18  // //
19  // The iLab Neuromorphic Robotics Toolkit is free software: you can //
20  // redistribute it and/or modify it under the terms of the GNU General //
21  // Public License as published by the Free Software Foundation, either //
22  // version 3 of the License, or (at your option) any later version. //
23  // //
24  // The iLab Neuromorphic Robotics Toolkit is distributed in the hope //
25  // that it will be useful, but WITHOUT ANY WARRANTY; without even the //
26  // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //
27  // PURPOSE. See the GNU General Public License for more details. //
28  // //
29  // You should have received a copy of the GNU General Public License //
30  // along with The iLab Neuromorphic Robotics Toolkit. If not, see //
31  // <http://www.gnu.org/licenses/>. //
32  // ////////////////////////////////////////////////////////////////////////
33  @endverbatim */
34 
35 #ifndef INCLUDE_NRT_GRAPHICS_SHAPERENDERERBASIC_H
36 #define INCLUDE_NRT_GRAPHICS_SHAPERENDERERBASIC_H
37 
40 #include <nrt/Eigen/Eigen.H>
41 
42 // need to test for these at config...
43 #include <X11/Xlib.h>
44 #include <X11/Xutil.h>
45 
46 // Expose OpenGL 3.0 prototypes, which are used in particular by VBO:
47 #define GL_GLEXT_PROTOTYPES 1
48 #define GL3_PROTOTYPES 1
49 
50 #include <GL/gl.h>
51 #include <GL/glx.h>
52 
53 namespace nrt
54 {
55  namespace graphics
56  {
57  //! Namespace for ShapeRenderer parameters
58  namespace shaperendererbasic
59  {
60  //! Parameter category definition
61  static nrt::ParameterCategory const ParamCateg("ShapeRendererBasic Options");
62 
63  //! Parameter definition for display dims
64  NRT_DECLARE_PARAMETER_WITH_CALLBACK(dims, nrt::Dims<nrt::int32>, "Rendered display dimemsions in pixels",
65  nrt::Dims<nrt::int32>(640, 480), ParamCateg);
66 
67  //! Parameter definition for wireframe
68  NRT_DECLARE_PARAMETER(wireframe, bool, "Use wireframe instead of full-3D display", false, ParamCateg);
69 
70  //! Parameter definition for window title
71  NRT_DECLARE_PARAMETER(windowtitle, std::string, "Title of the window", "ShapeRendererBasic Window", ParamCateg);
72 
73  //! Parameter definition for fog density
74  NRT_DECLARE_PARAMETER(fogdensity, float, "Fog density between 0.0 and 1.0 (value 0.0 turns off fog effects)",
75  0.0F, ParamCateg);
76 
77  //! Parameter definition for fog color
79  "Fog color RGB (only applies if fog-density is > 0.0)",
80  nrt::PixRGB<nrt::byte>(128, 128, 128), ParamCateg);
81 
82  //! Parameter definition for detail
83  NRT_DECLARE_PARAMETER(detail, unsigned int,
84  "Detail level used to render spheres, cylinders, etc. Larger values create more "
85  "subdivisions, which is slower to render but looks smoother.", 30U, ParamCateg);
86 
87  //! Parameter definition for light ambient
88  NRT_DECLARE_PARAMETER(ambientlight, nrt::PixRGB<nrt::byte>, "Ambient light color and intensity (R,G,B)",
89  nrt::PixRGB<nrt::byte>(100, 100, 100), ParamCateg);
90 
91  //! Parameter definition for light diffuse
92  NRT_DECLARE_PARAMETER(diffuselight, nrt::PixRGB<nrt::byte>, "Diffuse light color and intensity (R,G,B)",
93  nrt::PixRGB<nrt::byte>(255, 255, 255), ParamCateg);
94 
95  //! Parameter definition for light specular
96  NRT_DECLARE_PARAMETER(specularlight, nrt::PixRGB<nrt::byte>, "Specular light color and intensity (R,G,B)",
97  nrt::PixRGB<nrt::byte>(255, 255, 255), ParamCateg);
98 
99  //! Parameter definition for light diffuse
100  NRT_DECLARE_PARAMETER(lightposition, Eigen::Vector3f, "Light position (X,Y,Z)",
101  Eigen::Vector3f(-50.0F, 0.0F, 100.0F), ParamCateg);
102  }
103 
104 
105  //! Render Shape objects into a basic X11/OpenGL window
106  /*! \ingroup graphics */
109  public nrt::Parameter<shaperendererbasic::dims, shaperendererbasic::wireframe,
110  shaperendererbasic::windowtitle, shaperendererbasic::fogdensity,
111  shaperendererbasic::fogcolor, shaperendererbasic::detail,
112  shaperendererbasic::ambientlight, shaperendererbasic::diffuselight,
113  shaperendererbasic::specularlight, shaperendererbasic::lightposition>
114  {
115  public:
116  //! Default constructor
117  /*! This should do very little, most initialization should happen in preInit(). \see Component */
118  ShapeRendererBasic(std::string const & instanceName = "");
119 
120  //! Virtual destructor for safe inheritance
121  virtual ~ShapeRendererBasic();
122 
123  //! \defgroup srbinterface Interface functions that should all be called from a same thread
124  /*! An OpenGL context is attached to a given thread, hence all of the renderer's display functions should be
125  called from the same thread. Typically, that would teh the run() thread of an nrt::Component, as follows:
126  @code
127 void MyModule::run()
128 {
129  // Get our renderer going:
130  itsRenderer->createContext();
131  itsRenderer->lookAt(Eigen::Vector3d(0, -100, 100), Eigen::Vector3d(0, 0, 0), Eigen::Vector3d::UnitZ());
132 
133  // Main loop:
134  while (running())
135  {
136  // Reset our frame to blank:
137  itsRenderer->initFrame();
138 
139  // Now render all our shapes:
140  for (auto const & s : my_shapes) s.render(*itsRenderer);
141 
142  // Finalize rendering of the frame:
143  itsRenderer->renderFrame();
144 
145  // Maybe sleep a bit, or compute FPS, etc
146  std::this_thread::sleep_for(std::chrono::milliseconds(10));
147  }
148 
149  // Time to cleanup and close down:
150  itsRenderer->destroyContext();
151 }
152  @endcode */
153  //!@{
154  //! Create a drawing context
155  void createContext();
156 
157  //! Optional, activate the context (after it is created by createContext()); initFrame() does this too
158  void activateContext();
159 
160  //! Reset our display buffer to blank
161  void initFrame();
162 
163  //! Render the display buffer to screen
164  void renderFrame();
165 
166  //! Destroy our drawing context
167  void destroyContext();
168 
169  //!@}
170 
171  //! Get dimensions of renderer
172  virtual Dims<int32> dims() const;
173 
174  //! Look at the target from the specified location
175  /*! @param[in] eye Location to look from
176  @param[in] target Location to look at
177  @param[in] up Direction to consider up for camera */
178  void lookAt(Eigen::Vector3d const & eye, Eigen::Vector3d const & target, Eigen::Vector3d const & up);
179 
180  //! Primitive shapes optimized as DisplayLists
181  /*! Before you call any of these functions, you should already have obtained a glX context lock. Mainly, these
182  functions are for the use of programmers that code complex shapes as assemblages of these elementary shapes;
183  end users should just use Shape objects instead. For example, use render() on a Sphere shape instead of
184  calling drawSphere() here (indeed, render() for a Sphere just calls drawSphere() internally after setting up
185  the transform, Brush, Pen, etc). */
186  //!@{
187  //! Draw a unit sphere
188  void drawSphere() const;
189 
190  //! Draw a unit cylinder
191  void drawCylinder(bool capped) const;
192 
193  //!@}
194 
195  //! Set a callback to be called whenever a key is pressed
196  void setKeyboardCallback(std::function<void(std::vector<nrt::graphics::ShapeRenderer::KeyboardPress>)> callback);
197 
198  protected:
199  //! Open the window and do initial setups
200  virtual void preStart();
201 
202  //! Function called when a window resize event is received, or user changes the dims parameter
203  virtual void resizeCallback(int width, int height);
204 
205  //! Function called when a mouse event is received
206  virtual void mouseCallback(unsigned int button, int x, int y, bool pushed, bool motion);
207 
208  //! Function called when a keyboard event is received
209  virtual void keyboardCallback(std::vector<nrt::graphics::ShapeRenderer::KeyboardPress> const & keys);
210 
211  //! Function called when a 3D mouse (3dConnexion SpacePilot Pro for example) event is received
212  virtual void mouse3dCallback(double const x, double const y, double const z,
213  double const a, double const b, double const c, int const period);
214 
215  //! Close down the window
216  virtual void postStop();
217 
218  Display *itsDisplay;
219  XVisualInfo *itsVisualInfo;
220  Window itsWindow;
221  GLXFBConfig itsFBConfig;
222  GLXContext itsCtx;
223  XSetWindowAttributes itsSwa;
224 
225  private:
226  void onParamChange(nrt::graphics::shaperendererbasic::dims const & param, nrt::Dims<nrt::int32> const & di);
227  void handleEvents();
228 
229  //! The position of the mouse when the mouse callback is first called
230  int itsMouseX, itsMouseY;
231 
232  //! The mouse button currently pressed, if any
233  unsigned int itsMouseButton;
234 
235  //! Used to detect first key press
236  std::array<bool, 6> itsKeyPressed;
237 
238  Atom itsMagellanMotionEvent; //!< 3dconnexion 3d mouse motion event
239  Atom itsMagellanButtonPressEvent; //!< 3dconnexion 3d mouse ButtonPressEvent
240  Atom itsMagellanButtonReleaseEvent; //!< 3dconnexion 3d mouse ButtonReleaseEvent
241  Atom itsMagellanCommandEvent; //!< 3dconnexion 3d mouse CommandEvent
242 
243  Atom itsDeleteMessage; // used for catching window closure
244 
245  struct ContextLock
246  {
247  ContextLock(ShapeRendererBasic * sr_);
248  ~ContextLock();
249  private:
250  ShapeRendererBasic * sr;
251  std::lock_guard<std::mutex> lg;
252  };
253 
254  friend struct ContextLock;
255 
256  mutable std::mutex itsMutex;
257  bool itsHasContext;
258 
259  Eigen::Vector3d itsEye;
260  Eigen::Vector3d itsTarget;
261  Eigen::Vector3d itsUp;
262 
263  unsigned int itsSphereDL;
264  unsigned int itsCylinderDL;
265  unsigned int itsCappedCylinderDL;
266 
267  std::function<void(std::vector<nrt::graphics::ShapeRenderer::KeyboardPress>)> itsUserKeyboardCallback;
268  };
269 
270  } // namespace graphics
271 } // namespace nrt
272 
273 
274 
275 #endif // INCLUDE_NRT_GRAPHICS_SHAPERENDERERBASIC_H