1 // -*- c-basic-offset: 4 -*- 2 3 /** @file ViewState.h 4 * 5 * @author James Legg 6 * @author Darko Makreshanski 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public 10 * License as published by the Free Software Foundation; either 11 * version 2 of the License, or (at your option) any later version. 12 * 13 * This software is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public 19 * License along with this software. If not, see 20 * <http://www.gnu.org/licenses/>. 21 * 22 */ 23 24 /* A ViewState or VisualizationState holds information about what is visible, the state of the 25 * various bits of the panorama as it is shown in a preview, and the scaling of 26 * the preview. The state of the panorama options and images are stored so 27 * that we can continuously change properties interactively without bothering 28 * the real panorama object and therefore the undo / redo history. The classes 29 * also manages what needs to be recalculated to update the view. 30 * 31 * When a change occurs, we examine any differences with our stored state that 32 * we care about. It doesn't matter if the change is caused by an interactive 33 * tool or an update to the panorama object. 34 * If we find a change that makes our preview out of sync, we record what needs 35 * to be done to bring it up to date. Note some changes do not create any 36 * difference to the preview, so we don't even want to redraw sometimes. 37 * After the changes have been made, we can state what needs redoing when asked. 38 * The texture manager and mesh manager will ask what they need to do. 39 * After that, any changes we suggested should have been made, and FinishDraw() 40 * is called. At this point we declare everything is clean and up to date again. 41 * 42 * We don't intitiate the calculations ourself when doing things interactively 43 * so we can group several changes together, e.g. when dragging a group of 44 * images together SetSrcImage is called for each image but we only want to 45 * redraw after they have all been moved. However, when the panorama changes 46 * we want to initiate an update the preview ourself, so all the main GUI 47 * interactions work. 48 * 49 * The information is divided into two classes: 50 * - The first class is the ViewState class which holds information that is 51 * relevant for all Visualizations like the preview, panosphere or plane. 52 * This is mainly dominated by the manipulation of the Textures related stuff 53 * which are the same for all visualizations. 54 * The ViewState also encapsulates all the VisualizationState in itself so that 55 * it can properly inform them when any change occurs 56 * 57 * - The second class is the VisualizationState class which is subclassed for each 58 * type of visualization. The VisualizationState class holds information specific 59 * to each visualization. This includes the state of the meshes, state of the viewport, etc. 60 * 61 */ 62 63 #ifndef __VIEWSTATE_H 64 #define __VIEWSTATE_H 65 66 #include "base_wx/wxutils.h" 67 #include <panodata/PanoramaData.h> 68 #include <panodata/Panorama.h> 69 #include "OutputProjectionInfo.h" 70 #include <vigra/diff2d.hxx> 71 #include "TextureManager.h" 72 #include "MeshManager.h" 73 74 #include <panodata/PanoramaOptions.h> 75 76 class GLViewer; 77 class VisualizationState; 78 79 80 class ViewState : public HuginBase::PanoramaObserver 81 { 82 public: 83 // constructor: we need to know what panorama we deal with. 84 ViewState(HuginBase::Panorama *pano, bool supportMultiTexture); 85 ~ViewState(); 86 // when the real panorama changes, we want to update ourself to reflect it. 87 // we will force a redraw if anything worthwhile changes. 88 void panoramaChanged(HuginBase::Panorama &pano); 89 void panoramaImagesChanged(HuginBase::Panorama&, const HuginBase::UIntSet&); 90 91 // For interactive control, the real panorama does not change. Instead one 92 // of the following functions will be called: 93 void SetOptions(const HuginBase::PanoramaOptions *new_opts); 94 void SetSrcImage(unsigned int image_nr, HuginBase::SrcPanoImage *new_img); 95 void SetLens(unsigned int lens_nr, HuginBase::Lens *new_lens); 96 // someone else decides we need to redraw next time around. 97 void ForceRequireRedraw(); 98 // then we compare with the stored state and set dirty flags as neceassry. 99 100 HuginBase::PanoramaOptions *GetOptions(); 101 OutputProjectionInfo *GetProjectionInfo(); 102 HuginBase::SrcPanoImage *GetSrcImage(unsigned int image_nr); 103 GetTextureManager()104 TextureManager * GetTextureManager() {return m_tex_manager;} 105 GetSupportMultiTexture()106 bool GetSupportMultiTexture() const { return m_multiTexture; }; 107 // These functions are used to identify what needs to be redone on the next 108 // redraw. 109 // return true if we should update a texture's photometric correction 110 bool RequireRecalculatePhotometric(); 111 // return true if we should check the generated mip levels of the textures 112 bool RequireRecalculateImageSizes(); 113 // return true if we should update a mask 114 bool RequireRecalculateMasks(unsigned int image_nr); 115 // return true if images have been removed 116 bool ImagesRemoved(); 117 118 // this is called when a draw has been performed, so we can assume the 119 // drawing state (textures, meshes) are now all up to date. 120 void FinishedDraw(); 121 122 // update the meshes and textures as necessary before drawing. 123 void DoUpdates(); 124 125 void Redraw(); 126 127 std::map<VisualizationState*, bool> vis_states; 128 129 protected: 130 131 HuginBase::Panorama *m_pano; 132 std::map<unsigned int, HuginBase::SrcPanoImage> img_states; 133 HuginBase::PanoramaOptions opts; 134 OutputProjectionInfo *projection_info; 135 // std::map<unsigned int, HuginBase::Lens> lens_states; 136 unsigned int number_of_images; 137 class fbool // a bool that initialises to false. 138 { 139 public: fbool()140 fbool() 141 { 142 val = false; 143 } 144 bool val; 145 }; 146 // what needs redoing? 147 bool dirty_photometrics; 148 std::map<unsigned int, bool> active; 149 std::map<unsigned int, fbool> dirty_mask; 150 bool dirty_image_sizes, images_removed; 151 // reset all the dirty flags. 152 void Clean(); 153 154 // this stores all the textures we need. 155 TextureManager *m_tex_manager; 156 bool m_multiTexture; 157 }; 158 159 class VisualizationState 160 { 161 public: 162 163 template <class M> VisualizationState(HuginBase::Panorama * pano,ViewState * view_state,GLViewer * viewer,void (* RefreshFunction)(void *),void * arg,M * classArg)164 VisualizationState(HuginBase::Panorama* pano, ViewState* view_state, GLViewer * viewer, void (*RefreshFunction)(void*), void *arg, M* classArg) 165 { 166 m_pano = pano; 167 m_view_state = view_state; 168 RefreshFunc = RefreshFunction; 169 refreshArg = arg; 170 dirty_draw = true; 171 dirty_viewport = true; 172 unsigned int number_of_images = m_pano->getNrOfImages(); 173 for (unsigned int img = 0; img < number_of_images; img++) 174 { 175 dirty_mesh[img].val = true; 176 } 177 genscale = 0.0; 178 m_mesh_manager = new M(m_pano, this); 179 m_view_state->vis_states[this] = true; 180 m_viewer = viewer; 181 m_zoom = 1.0; 182 m_lookAt = hugin_utils::FDiff2D(0.5, 0.5); 183 } 184 185 virtual ~VisualizationState(); 186 187 virtual HuginBase::PanoramaOptions *GetOptions(); 188 virtual OutputProjectionInfo *GetProjectionInfo(); 189 virtual HuginBase::SrcPanoImage *GetSrcImage(unsigned int image_nr); 190 SetOptions(const HuginBase::PanoramaOptions * new_opts)191 virtual void SetOptions(const HuginBase::PanoramaOptions *new_opts) {} SetSrcImage(unsigned int image_nr,HuginBase::SrcPanoImage * new_img)192 virtual void SetSrcImage(unsigned int image_nr, HuginBase::SrcPanoImage * new_img) {} 193 194 // return true if we need to recalculate the mesh 195 bool RequireRecalculateMesh (unsigned int image_nr); 196 // return true if we need to redraw at all 197 bool RequireDraw(); 198 // return true if we should check the renderers' viewport 199 bool RequireRecalculateViewport(); 200 201 // the scale is the number of screen pixels per panorama pixel. 202 float GetScale(); 203 void SetScale(float scale); 204 205 // stuff used directly for drawing the preview, made accessible for tools. 206 unsigned int GetMeshDisplayList(unsigned int image_nr); GetMeshManager()207 MeshManager * GetMeshManager() {return m_mesh_manager;} 208 209 void FinishedDraw(); 210 211 // The visible area is the part of the panarama visible in the view. The 212 // coordinates are in panorama pixels. SetVisibleArea(vigra::Rect2D area)213 void SetVisibleArea(vigra::Rect2D area) 214 { 215 /* TODO with zooming, update meshes that were generated with this area 216 * in mind. Zooming changes the scale, which updates the meshes. 217 * Panning on the other hand needs to recalculate meshes as they can 218 * ignore the stuff off-screen 219 */ 220 visible_area = area; 221 } GetVisibleArea()222 vigra::Rect2D GetVisibleArea() 223 { 224 return visible_area; 225 } 226 /**/ GetZoomLevel()227 double GetZoomLevel() const 228 { 229 return m_zoom; 230 }; 231 void SetZoomLevel(const float new_zoom); GetViewingCenter()232 hugin_utils::FDiff2D GetViewingCenter() const 233 { 234 return m_lookAt; 235 }; 236 void SetViewingCenter(const hugin_utils::FDiff2D& center); 237 void SetCanvasSize(const vigra::Size2D& canvasSize); 238 getViewState()239 ViewState* getViewState() {return m_view_state;} 240 241 // redraw the preview, but only if something has changed. 242 void Redraw(); 243 244 // update the meshes and textures as necessary before drawing. 245 void DoUpdates(); 246 SetDirtyMesh(int image_nr)247 void SetDirtyMesh(int image_nr) {dirty_mesh[image_nr].val = true;} 248 void ForceRequireRedraw(); SetDirtyViewport()249 void SetDirtyViewport() {dirty_viewport = true;} 250 GetViewer()251 GLViewer * GetViewer() {return m_viewer;} 252 253 protected: 254 255 HuginBase::Panorama *m_pano; 256 257 class fbool // a bool that initialises to false. 258 { 259 public: fbool()260 fbool() 261 { 262 val = false; 263 } 264 bool val; 265 }; 266 // redoing specific only for a certain visualization 267 std::map<unsigned int, fbool> dirty_mesh; 268 bool dirty_draw, dirty_viewport; 269 270 float scale, genscale, gl_scale; 271 vigra::Rect2D visible_area; 272 hugin_utils::FDiff2D m_lookAt; 273 float m_zoom; 274 vigra::Size2D m_canvasSize; 275 void (*RefreshFunc)(void *); 276 void *refreshArg; 277 278 // this stores all the meshes we need. 279 MeshManager *m_mesh_manager; 280 ViewState *m_view_state; 281 282 GLViewer * m_viewer; 283 private: 284 // don't copy this class 285 VisualizationState(const VisualizationState& other); 286 VisualizationState& operator=(const VisualizationState& other); 287 }; 288 289 class OverviewVisualizationState : public VisualizationState 290 { 291 public: 292 template <class M> OverviewVisualizationState(HuginBase::Panorama * pano,ViewState * view_state,GLViewer * viewer,void (* RefreshFunction)(void *),void * arg,M * classArg)293 OverviewVisualizationState(HuginBase::Panorama* pano, ViewState* view_state, GLViewer * viewer, void(*RefreshFunction)(void*), void *arg, M* classArg) 294 : VisualizationState(pano, view_state, viewer, RefreshFunction, arg, (M*) classArg) {} 295 296 }; 297 298 class PanosphereOverviewVisualizationState : public OverviewVisualizationState 299 { 300 public: 301 302 PanosphereOverviewVisualizationState(HuginBase::Panorama* pano, ViewState* view_state, GLViewer * viewer, void(*RefreshFunction)(void*), void *arg); 303 ~PanosphereOverviewVisualizationState(); 304 305 HuginBase::PanoramaOptions *GetOptions(); 306 OutputProjectionInfo *GetProjectionInfo(); 307 308 // HuginBase::SrcPanoImage *GetSrcImage(unsigned int image_nr); 309 // void SetSrcImage(unsigned int image_nr, HuginBase::SrcPanoImage * new_img ); 310 311 void SetOptions(const HuginBase::PanoramaOptions * new_opts); 312 313 //camera properties getAngY()314 double getAngY() {return angy;} getAngX()315 double getAngX() {return angx;} getR()316 double getR() {return R;} getFOV()317 double getFOV() {return fov;} 318 getSphereRadius()319 double getSphereRadius() {return sphere_radius;} 320 321 void setAngX(double angx_in); 322 void setAngY(double angy_in); setR(double r)323 void setR(double r) {R = r;} 324 325 326 protected: 327 328 double angy; 329 double angx; 330 double R; 331 double fov; 332 333 double sphere_radius; 334 335 // std::map<unsigned int, HuginBase::SrcPanoImage> img_states; 336 HuginBase::PanoramaOptions opts; 337 OutputProjectionInfo *projection_info; 338 339 340 }; 341 342 class PlaneOverviewVisualizationState : public OverviewVisualizationState 343 { 344 public: 345 346 PlaneOverviewVisualizationState(HuginBase::Panorama* pano, ViewState* view_state, GLViewer * viewer, void(*RefreshFunction)(void*), void *arg); 347 ~PlaneOverviewVisualizationState(); 348 349 HuginBase::PanoramaOptions *GetOptions(); 350 OutputProjectionInfo *GetProjectionInfo(); 351 352 void SetOptions(const HuginBase::PanoramaOptions * new_opts); 353 354 //camera properties getR()355 double getR() {return R;} getFOV()356 double getFOV() {return fov;} getX()357 double getX() {return X;} getY()358 double getY() {return Y;} 359 setR(double r)360 void setR(double r) {R = r;} setX(double x)361 void setX(double x) {X = x;} setY(double y)362 void setY(double y) {Y = y;} 363 364 protected: 365 366 double X; 367 double Y; 368 double R; 369 double fov; 370 371 HuginBase::PanoramaOptions opts; 372 OutputProjectionInfo *projection_info; 373 374 }; 375 376 #endif 377 378