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