ARGoS
3
A parallel, multi-engine simulator for swarm robotics
|
00001 00007 #ifndef QTOPENGL_USER_FUNCTIONS_H 00008 #define QTOPENGL_USER_FUNCTIONS_H 00009 00010 namespace argos { 00011 class CQTOpenGLUserFunctions; 00012 class CFloorEntity; 00013 } 00014 00015 class QPainter; 00016 00017 #include <argos3/plugins/simulator/visualizations/qt-opengl/qtopengl_widget.h> 00018 #include <argos3/core/utility/datatypes/color.h> 00019 #include <argos3/core/utility/math/quaternion.h> 00020 00021 namespace argos { 00022 00072 class CQTOpenGLUserFunctions { 00073 00074 public: 00075 00079 CQTOpenGLUserFunctions(); 00080 00084 virtual ~CQTOpenGLUserFunctions(); 00085 00089 virtual void Draw(CFloorEntity& c_entity) {} 00090 00096 virtual void DrawInWorld() {} 00097 00105 virtual void DrawOverlay(QPainter& c_painter) {} 00106 00111 inline CQTOpenGLWidget& GetOpenGLWidget() { 00112 return *m_pcQTOpenGLWidget; 00113 } 00114 00119 inline void SetOpenGLWidget(CQTOpenGLWidget& c_widget) { 00120 m_pcQTOpenGLWidget = &c_widget; 00121 } 00122 00134 void DrawTriangle(const CVector3& c_center_offset = CVector3::ZERO, 00135 const CColor& c_color = CColor::RED, 00136 const bool b_fill = true, 00137 const CQuaternion& c_orientation = CQuaternion(), 00138 Real f_base = 0.2f, 00139 Real f_height = 0.1732050808f); 00140 00152 void DrawCircle(Real f_radius = 0.1f, 00153 const CVector3& c_center_offset = CVector3::ZERO, 00154 const CColor& c_color = CColor::RED, 00155 const bool b_fill = true, 00156 const CQuaternion& c_orientation = CQuaternion(), 00157 GLuint un_vertices = 20); 00158 00159 00171 void DrawCylinder(Real f_radius=0.1f, 00172 Real f_height=0.1f, 00173 const CVector3& c_center_offset = CVector3::ZERO, 00174 const CColor& c_color = CColor::RED, 00175 const CQuaternion& c_orientation = CQuaternion(), 00176 GLuint un_vertices = 20); 00177 00178 00190 void DrawSegment(const CVector3& c_end_point = CVector3(1.0f,0.0f,1.0f), 00191 const CVector3& c_start_point = CVector3::ZERO, 00192 const CColor& c_segment_color = CColor::RED, 00193 const Real& f_line_width = 1.0f, 00194 bool b_draw_end_point = false, 00195 bool b_draw_start_point = false, 00196 const CColor& c_end_point_color = CColor::RED, 00197 const CColor& c_start_point_color = CColor::RED); 00198 00205 void DrawPolygon(const std::vector<CVector3>& vec_points, 00206 const CColor& c_color = CColor::RED); 00207 00208 00216 void DrawPoint(const CVector3& c_position = CVector3(1.0f,0.0f,1.0f), 00217 const CColor& c_color = CColor::RED, 00218 const Real f_point_diameter = 5.0); 00219 00220 private: 00221 00226 typedef void (CQTOpenGLUserFunctions::*TThunk)(CEntity&); 00227 00237 template <typename USER_IMPL, typename ENTITY> 00238 void Thunk(CEntity& c_entity); 00239 00244 class CFunctionHolder {}; 00245 00253 template <typename USER_IMPL, typename ENTITY> class CFunctionHolderImpl : public CFunctionHolder { 00254 public: 00255 typedef void (USER_IMPL::*TFunction)(ENTITY&); 00256 TFunction Function; 00257 CFunctionHolderImpl(TFunction t_function) : Function(t_function) {} 00258 }; 00259 00265 CVTable<CQTOpenGLUserFunctions, CEntity, TThunk> m_cThunks; 00266 00271 std::vector<CFunctionHolder*> m_vecFunctionHolders; 00272 00273 public: 00274 00281 template <typename USER_IMPL, typename ENTITY> 00282 void RegisterUserFunction(void(USER_IMPL::*pt_function)(ENTITY&)); 00283 00288 void Call(CEntity& c_entity); 00289 00290 private: 00291 00295 CQTOpenGLWidget* m_pcQTOpenGLWidget; 00296 00297 }; 00298 00299 /****************************************/ 00300 /****************************************/ 00301 00302 template <typename USER_IMPL, typename ENTITY> 00303 void CQTOpenGLUserFunctions::Thunk(CEntity& c_entity) { 00304 /* 00305 * When this method is called, the static type of 'this' 00306 * is CQTOpenGLUserFunctions. Since we want to call 00307 * method in USER_IMPL (subclass of CQTOpenGLUserFunctions), 00308 * we need a cast. The cast is static because we trust 00309 * the user on not doing anything stupid. 00310 * The variable cImpl can be static because the cast is necessary 00311 * only the first time this function is called. 00312 */ 00313 static USER_IMPL& cImpl = static_cast<USER_IMPL&>(*this); 00314 /* Cast the argument to the right type */ 00315 ENTITY& cEntity = static_cast<ENTITY&>(c_entity); 00316 /* Cast the function holder to its effective type */ 00317 CFunctionHolderImpl<USER_IMPL,ENTITY>& cFunctionHolder = static_cast<CFunctionHolderImpl<USER_IMPL,ENTITY>&>(*m_vecFunctionHolders[GetTag<ENTITY,CEntity>()]); 00318 /* Call the user-defined method */ 00319 (cImpl.*(cFunctionHolder.Function))(cEntity); 00320 } 00321 00322 template <typename USER_IMPL, typename ENTITY> 00323 void CQTOpenGLUserFunctions::RegisterUserFunction(void(USER_IMPL::*pt_function)(ENTITY&)) { 00324 /* Add the thunk to the VTable */ 00325 m_cThunks.Add<ENTITY>(&CQTOpenGLUserFunctions::Thunk<USER_IMPL,ENTITY>); 00326 /* Add the function holder to the vector, padding gaps with NULL pointers */ 00327 size_t unIdx = GetTag<ENTITY,CEntity>(); 00328 if(m_vecFunctionHolders.size() <= unIdx) { 00329 m_vecFunctionHolders.resize(unIdx+1, NULL); 00330 } 00331 m_vecFunctionHolders[unIdx] = new CFunctionHolderImpl<USER_IMPL,ENTITY>(pt_function); 00332 } 00333 00334 /****************************************/ 00335 /****************************************/ 00336 00337 } 00338 00339 /* Definitions useful for dynamic linking of user functions */ 00340 #define REGISTER_QTOPENGL_USER_FUNCTIONS(CLASSNAME, LABEL) \ 00341 REGISTER_SYMBOL(CQTOpenGLUserFunctions, \ 00342 CLASSNAME, \ 00343 LABEL, \ 00344 "undefined", \ 00345 "undefined", \ 00346 "undefined", \ 00347 "undefined", \ 00348 "undefined") 00349 00350 #endif