Hugintrunk  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ViewState.cpp
Go to the documentation of this file.
1 // -*- c-basic-offset: 4 -*-
2 
24 #ifdef __WXMAC__
25 #include "panoinc_WX.h"
26 #include "panoinc.h"
27 #endif
28 
29 #include "ViewState.h"
30 #include "MeshManager.h"
31 
32 ViewState::ViewState(HuginBase::Panorama *pano, bool supportMultiTexture)
33 {
34 
35 
36  m_pano = pano;
37  m_multiTexture=supportMultiTexture;
38  m_pano->addObserver(this);
39  // we will need to update everything for this panorama.
40  dirty_image_sizes = true;
41  images_removed = true;
42  dirty_photometrics = true;
44  for (unsigned int img = 0; img < number_of_images; img++)
45  {
46  img_states[img] = m_pano->getSrcImage(img);
47  dirty_mask[img].val = false;
48  }
49  opts = m_pano->getOptions();
51  // now set the texture manager up.
52  m_tex_manager = new TextureManager(m_pano, this);
53 }
54 
56 {
57  m_pano->removeObserver(this);
58  delete projection_info;
59  delete m_tex_manager;
60 }
61 
62 
64 {
65 
66  bool require_draw=false;
67 
68  // anything could have happened, check everything.
70  SetOptions(&new_opts);
71  unsigned int imgs = m_pano->getNrOfImages();
72  for (unsigned int img = 0; img < imgs; img++)
73  {
74  HuginBase::SrcPanoImage new_image = m_pano->getSrcImage(img);
75  SetSrcImage(img, &new_image);
76  // has the enabled state changed in the preview?
77  bool new_active = m_pano->getImage(img).getActive();
78  if (new_active != active[img])
79  {
80  require_draw = true;
81  active[img] = new_active;
82  }
83  }
84  // has the number of images changed?
85  if (imgs < number_of_images)
86  {
87  // we've lost some
88  dirty_image_sizes = true;
89  require_draw = true;
90  images_removed = true;
91  } else if (imgs > number_of_images)
92  {
93  // added images. Assume it doesn't affect the rest.
94  dirty_image_sizes = true;
95  require_draw = true;
96  // FIXME more might need to be done, if the new images are not the last
97  // ones in order of image number.
98  }
99  number_of_images = imgs;
100 
101  if (require_draw) {
102  //refresh function is called in the respective VisualizationState callback
103  for (std::map<VisualizationState*,bool>::iterator it = vis_states.begin() ; it != vis_states.end() ; ++it) {
104  DEBUG_DEBUG("PanoChanged - iterator before");
105  if (it->second) {
106  DEBUG_DEBUG("PanoChanged - iterator after");
107  it->first->Redraw();
108  }
109  }
110  }
111 
112 }
113 
115  const HuginBase::UIntSet&)
116 {
117  // actually this stuff is handled by panoramaChanged.
118 }
119 
121 {
122 
123  bool dirty_projection = false;
124 
125  for (std::map<VisualizationState*,bool>::iterator it = vis_states.begin() ; it != vis_states.end() ; ++it) {
126 
127  if (!(it->second)) continue;
128 
129  // compare the options
130  if ( new_opts->getSize() != opts.getSize()
131  || new_opts->getProjection() != opts.getProjection()
133  || new_opts->getHFOV() != opts.getHFOV()
134  || new_opts->getVFOV() != opts.getVFOV()
135  )
136  {
137  // output projection changed. All images' meshes need recalculating.
138  unsigned int imgs = m_pano->getNrOfImages();
139  for (unsigned int img = 0; img < imgs; img++)
140  {
141  it->first->SetDirtyMesh(img);
142  }
143  // we should also change the viewport to fit new the dimensions.
144  dirty_projection = true;
145  it->first->SetDirtyViewport();
146  it->first->ForceRequireRedraw();
147  }
148  if ((new_opts->outputExposureValue != opts.outputExposureValue) ||
150  {
151  // output exposure changed. All image photometrics are now different.
152  it->first->SetDirtyViewport();
153  dirty_photometrics = true;
154  }
155  if ( new_opts->getROI() != opts.getROI()
156  )
157  {
158  // this is all done every frame anyway.
159  it->first->ForceRequireRedraw();
160  }
161 
162  it->first->SetOptions(new_opts);
163 
164  }
165  // store the new options
166  opts = *new_opts;
167  if (dirty_projection)
168  {
169  // we need to update the projection info as well.
170  delete projection_info;
171  projection_info = 0;
173  }
174 }
175 
176 void ViewState::SetSrcImage(unsigned int image_nr, HuginBase::SrcPanoImage *new_img)
177 {
178  bool dirty_mesh = false;
179  bool dirty_draw = false;
180 
181  if (number_of_images <= image_nr)
182  {
183  // this must be an addition, since we didn't have this many images.
184  dirty_mesh = true;
185  dirty_image_sizes = true;
186  dirty_draw = true;
187  } else {
188  // compare the options
189  HuginBase::SrcPanoImage *img = &img_states[image_nr];
190  // if the filename has changed, something has probably been deleted
191  if (new_img->getFilename() != img->getFilename())
192  {
193  images_removed = true;
194  // since we use image numbers to identify meshes and images,
195  // we can't really tell what happened.
196  }
197  // has the projection changed?
198  if ( new_img->getRoll() != img->getRoll()
199  || new_img->getPitch() != img->getPitch()
200  || new_img->getYaw() != img->getYaw()
201  || new_img->getX() != img->getX()
202  || new_img->getY() != img->getY()
203  || new_img->getZ() != img->getZ()
204  || new_img->getHFOV() != img->getHFOV()
205  || new_img->getProjection() != img->getProjection()
206  || new_img->getShear() != img->getShear()
207  || new_img->getRadialDistortionCenterShift()
208  == img->getRadialDistortionCenterShift()
209  || new_img->getRadialDistortion() != img->getRadialDistortion()
210  || new_img->getCropRect() != img->getCropRect()
211  )
212  {
213  dirty_mesh = true;
214  dirty_draw = true;
215 // dirty_mesh[image_nr].val = true;
216  // the field of view affects the image size calculations.
217  if (new_img->getHFOV() != img->getHFOV())
218  {
219  dirty_image_sizes = true;
220  }
221  }
222  // photometric adjustments
223  if ( new_img->getVigCorrMode() != img->getVigCorrMode()
224  || new_img->getRadialVigCorrCoeff() != img->getRadialVigCorrCoeff()
225  || new_img->getRadialVigCorrCenterShift() !=
226  img->getRadialVigCorrCenterShift()
227  || new_img->getExposureValue() != img->getExposureValue()
228  || new_img->getGamma() != img->getGamma()
229  || new_img->getWhiteBalanceRed() != img->getWhiteBalanceRed()
230  || new_img->getWhiteBalanceBlue() != img->getWhiteBalanceBlue()
231  || new_img->getResponseType() != img->getResponseType()
232  )
233  {
234  // real time photometric correction just needs a redraw.
235  /* full photometric correction will be redone automatically by the
236  TextureManager next redraw. */
237  /* FIXME only white balance and exposure are actually used for
238  real-time photometric correction. */
239  dirty_draw = true;
240  }
241  // mask stuff
242  if(new_img->getActiveMasks() != img->getActiveMasks())
243  {
244  dirty_mask[image_nr].val = true;
245  dirty_draw=true;
246  };
247  }
248  // store the new options
249  img_states[image_nr] = *new_img;
250 
251 
252  for (std::map<VisualizationState*,bool>::iterator it = vis_states.begin() ; it != vis_states.end() ; ++it) {
253  if (!(it->second)) continue;
254  if (dirty_draw) it->first->ForceRequireRedraw();
255  if (dirty_mesh) it->first->SetDirtyMesh(image_nr);
256  it->first->SetSrcImage(image_nr, new_img);
257  }
258 
259 }
260 
262 {
263  // this is generally called by preview tools. We let them manage themselves.
264  // often they give some user interface thing that doesn't reflect a change
265  // in the panorama at all, so we let them force a redraw.
266  for (std::map<VisualizationState*,bool>::iterator it = vis_states.begin() ; it != vis_states.end() ; ++it) {
267  if (!(it->second)) continue;
268  it->first->ForceRequireRedraw();
269  }
270 }
271 
272 
274 {
275  return &opts;
276 }
277 
279 {
280  return projection_info;
281 }
282 
284 {
285  return &img_states[image_nr];
286 }
287 
288 
290 {
291  return dirty_image_sizes;
292 }
293 
295 {
296  return dirty_photometrics;
297 }
298 
300 {
301  return images_removed;
302 }
303 
304 bool ViewState::RequireRecalculateMasks(unsigned int image_nr)
305 {
306  if (number_of_images > image_nr)
307  {
308  return dirty_mask[image_nr].val;
309  }
310  return false;
311 }
312 
313 
315 {
316  // update our copy of the state and clear all the dirty flags.
318  img_states.clear();
319  active.clear();
320  for (unsigned int img = 0; img < number_of_images; img++)
321  {
322  img_states[img] = m_pano->getSrcImage(img);
323  active[img] = m_pano->getImage(img).getActive();
324  }
325  opts = m_pano->getOptions();
326 
327  Clean();
328 }
329 
331 {
332  dirty_image_sizes = false;
333  images_removed = false;
334  dirty_photometrics = false;
335  dirty_mask.clear();
336 }
337 
339 {
340  DEBUG_DEBUG("VIEW STATE DO UPDATES");
342  DEBUG_DEBUG("VIEW STATE END DO UPDATES");
343 }
344 
346 {
347 
348  for (std::map<VisualizationState*,bool>::iterator it = vis_states.begin() ; it != vis_states.end() ; ++it) {
349 
350  if (!(it->second)) continue;
351 
352  it->first->Redraw();
353 
354  }
355 
356 
357 }
358 
359 
360 
361 
362 
363 
364 
365 
367 {
368  m_view_state->vis_states[this] = false;
369  delete m_mesh_manager;
370 }
371 
372 
374 {
375  return scale;
376 }
377 
378 void VisualizationState::SetScale(float scale_in)
379 {
380  scale = scale_in;
381  // When resizing the window this can make the level detail of existing
382  // meshes be too high or low, but we don't want to do to much calculation
383  // so limit the forced recalculation of meshes to significant changes.
384  if (genscale == 0.0)
385  {
386  // should only happen the first time it is used. In which case we will
387  // regenerate the meshes anyways.
388  genscale = scale;
389  } else {
390  double difference = scale > genscale ?
392  if (difference > 1.25)
393  {
394  genscale = scale;
395  unsigned int number_of_images = m_pano->getNrOfImages();
396  for (unsigned int img = 0; img < number_of_images; img++)
397  {
398  dirty_mesh[img].val = true;
399  }
400  }
401  }
402 }
403 
404 
406 {
407  DEBUG_DEBUG("REDRAW OUT");
408  if (RequireDraw())
409  {
410  DEBUG_DEBUG("REDRAW IN");
412  }
413 }
414 
416 {
417  return dirty_viewport;
418 }
419 
420 bool VisualizationState::RequireRecalculateMesh (unsigned int image_nr)
421 {
422 
423  unsigned int number_of_images = m_pano->getNrOfImages();
424  if (number_of_images > image_nr)
425  {
426  return dirty_mesh[image_nr].val;
427  }
428  // if we didn't think there were enough images, create the mesh for the
429  // first time
430  return true;
431 }
432 
433 
435 {
436  return (dirty_draw);
437 }
438 
440 {
441  dirty_draw = true;
442 }
443 
445 {
446  DEBUG_DEBUG("VIS State Finished draw");
447  dirty_mesh.clear();
448  dirty_viewport = false;
449  dirty_draw = false;
451 }
452 
454 {
455  DEBUG_DEBUG("BEGIN UPDATES");
457  DEBUG_DEBUG("END UPDATES");
459  DEBUG_DEBUG("END UPDATES");
460 }
461 
462 unsigned int VisualizationState::GetMeshDisplayList(unsigned int image_number)
463 {
464  return m_mesh_manager->GetDisplayList(image_number);
465 }
466 
467 
469 {
470  return m_view_state->GetOptions();
471 }
472 
474 {
476 }
477 
479 {
480  return m_view_state->GetSrcImage(image_nr);
481 }
482 
483 void VisualizationState::SetZoomLevel(const float new_zoom)
484 {
485  // remember new zoom
486  // make sure that zoom remains in valid range
487  m_zoom = std::min(std::max(new_zoom, 1.0f), 50.0f);
488  // update center
491 }
492 
494 {
495  // set new center
496  // range check so that there no unnecessary black border remains
497  // we need the actual zoom factor, the width/height of the panorama
498  // and the width/height of the window
499  const double offset = 0.5 / m_zoom;
500  vigra::Size2D panoSize=m_view_state->GetOptions()->getSize();
501  double offsetx = offset;
502  double offsety = offset;
503  if (panoSize.width()*m_canvasSize.height() < m_canvasSize.width() * panoSize.height())
504  {
505  offsetx += ((double)m_canvasSize.width() / (double)m_canvasSize.height() * panoSize.height() / panoSize.width() - 1.0) / (2.0 * m_zoom);
506  offsetx = std::min(offsetx, 0.5);
507  }
508  else
509  {
510  offsety += ((double)m_canvasSize.height() / (double)m_canvasSize.width() * panoSize.width() / panoSize.height() - 1.0) / (2.0 * m_zoom);
511  offsety = std::min(offsety, 0.5);
512  };
513  m_lookAt = hugin_utils::simpleClipPoint(center, hugin_utils::FDiff2D(offsetx, offsety), hugin_utils::FDiff2D(1 - offsetx, 1 - offsety));
515 }
516 
517 void VisualizationState::SetCanvasSize(const vigra::Size2D& canvasSize)
518 {
519  m_canvasSize = canvasSize;
520  // update center
522 }
523 
524 PanosphereOverviewVisualizationState::PanosphereOverviewVisualizationState(HuginBase::Panorama* pano, ViewState* view_state, GLViewer * viewer, void (*RefreshFunction)(void*), void *arg)
525  : OverviewVisualizationState(pano, view_state, viewer, RefreshFunction, arg, (PanosphereOverviewMeshManager*) NULL)
526 {
527  scale = 1;
528 
529  angx = M_PI / 2.0;
530  angy = 0;
531  fov = 40;
532  R = 500;
533  m_insideView = true;
534  sphere_radius = 100;
535 
536  opts = (*(m_view_state->GetOptions()));
538  opts.setHFOV(360.0);
539  opts.setVFOV(180.0);
541 }
542 
544 {
545  delete projection_info;
546 }
547 
549 {
550  return &opts;
551 }
552 
554 {
555  return projection_info;
556 }
557 
559 {
560  opts = *new_opts;
562  opts.setHFOV(360.0);
563  opts.setVFOV(180.0);
564  delete projection_info;
566 }
567 
569 {
570  angx = angx_in;
571  dirty_draw = true;
572 }
573 
575 {
576  angy = angy_in;
577  dirty_draw = true;
578 }
579 
581 {
582  // limit new fov to 5 - 140 deg
583  fov = std::max(std::min(newFOV, 140.0), 5.0);
584 }
585 
587 {
588  if (m_insideView != insideView)
589  {
590  // inside/outside view changed, reset fov
591  setFOV(40);
592  m_insideView = insideView;
593  };
594 }
595 
596 PlaneOverviewVisualizationState::PlaneOverviewVisualizationState(HuginBase::Panorama* pano, ViewState* view_state, GLViewer * viewer, void(*RefreshFunction)(void*), void *arg)
597  : OverviewVisualizationState(pano, view_state, viewer, RefreshFunction, arg, (PlaneOverviewMeshManager*) NULL)
598 {
599 
600  scale = 1;
601 
602  fov = 60;
603  R = 500;
604  X = 0;
605  Y = 0;
606 
607  opts = (*(m_view_state->GetOptions()));
609  //TODO: hfov and vfov need to be divided into values for the output and values for the visualization
610  opts.setHFOV(90.0);
611  opts.setVFOV(90.0);
613 }
614 
616 {
617  delete projection_info;
618 }
619 
621 {
622  return &opts;
623 }
624 
626 {
627  return projection_info;
628 }
629 
631 {
632  opts = *new_opts;
634  opts.setHFOV(90.0);
635  opts.setVFOV(90.0);
636  delete projection_info;
638 }
639 
640 
HuginBase::PanoramaOptions opts
Definition: ViewState.h:375
PanosphereOverviewVisualizationState(HuginBase::Panorama *pano, ViewState *view_state, GLViewer *viewer, void(*RefreshFunction)(void *), void *arg)
Definition: ViewState.cpp:524
PanoramaOptions::ProjectionFormat getProjection() const
void SetScale(float scale)
Definition: ViewState.cpp:378
OutputProjectionInfo * projection_info
Definition: ViewState.h:376
void(* RefreshFunc)(void *)
Definition: ViewState.h:275
bool dirty_image_sizes
Definition: ViewState.h:150
SrcPanoImage getSrcImage(unsigned imgNr) const
get a description of a source image
Definition: Panorama.cpp:1620
void Clean()
Definition: ViewState.cpp:330
vigra::Size2D m_canvasSize
Definition: ViewState.h:274
void SetOptions(const HuginBase::PanoramaOptions *new_opts)
Definition: ViewState.cpp:558
bool removeObserver(PanoramaObserver *observer)
remove a panorama observer.
Definition: Panorama.cpp:1551
std::map< unsigned int, bool > active
Definition: ViewState.h:148
OutputProjectionInfo * GetProjectionInfo()
Definition: ViewState.cpp:278
void SetOptions(const HuginBase::PanoramaOptions *new_opts)
Definition: ViewState.cpp:630
void DoUpdates()
Definition: ViewState.cpp:338
void setInsideView(bool insideView)
Definition: ViewState.cpp:586
void ForceRequireRedraw()
Definition: ViewState.cpp:261
bool dirty_photometrics
Definition: ViewState.h:147
void Redraw()
Definition: ViewState.cpp:345
HuginBase::Panorama * m_pano
Definition: ViewState.h:255
void SetCanvasSize(const vigra::Size2D &canvasSize)
Definition: ViewState.cpp:517
include file for the hugin project
void ForceRequireRedraw()
Definition: ViewState.cpp:439
void FinishedDraw()
Definition: ViewState.cpp:314
hugin_utils::FDiff2D m_lookAt
Definition: ViewState.h:272
void panoramaChanged(HuginBase::Panorama &pano)
Notification about a Panorama change.
Definition: ViewState.cpp:63
MeshManager * m_mesh_manager
Definition: ViewState.h:279
HuginBase::PanoramaOptions * GetOptions()
Definition: ViewState.cpp:273
std::set< unsigned int > UIntSet
Definition: PanoramaData.h:51
HuginBase::PanoramaOptions opts
Definition: ViewState.h:340
const vigra::Rect2D & getROI() const
Model for a panorama.
Definition: Panorama.h:152
OutputProjectionInfo * GetProjectionInfo()
Definition: ViewState.cpp:625
void SetSrcImage(unsigned int image_nr, HuginBase::SrcPanoImage *new_img)
Definition: ViewState.cpp:176
bool m_multiTexture
Definition: ViewState.h:156
virtual HuginBase::SrcPanoImage * GetSrcImage(unsigned int image_nr)
Definition: ViewState.cpp:478
std::size_t getNrOfImages() const
number of images.
Definition: Panorama.h:205
std::map< unsigned int, fbool > dirty_mesh
Definition: ViewState.h:267
ViewState * m_view_state
Definition: ViewState.h:280
HuginBase::Panorama * m_pano
Definition: ViewState.h:131
virtual OutputProjectionInfo * GetProjectionInfo()
Definition: ViewState.cpp:473
bool RequireRecalculateViewport()
Definition: ViewState.cpp:415
HuginBase::PanoramaOptions opts
Definition: ViewState.h:133
OutputProjectionInfo * GetProjectionInfo()
Definition: ViewState.cpp:553
void SetViewingCenter(const hugin_utils::FDiff2D &center)
Definition: ViewState.cpp:493
void setHFOV(double h, bool keepView=true)
set the horizontal field of view.
void addObserver(PanoramaObserver *o)
add a panorama observer.
Definition: Panorama.cpp:1546
PlaneOverviewVisualizationState(HuginBase::Panorama *pano, ViewState *view_state, GLViewer *viewer, void(*RefreshFunction)(void *), void *arg)
Definition: ViewState.cpp:596
include file for the hugin project
const PanoramaOptions & getOptions() const
returns the options for this panorama
Definition: Panorama.h:481
bool RequireRecalculateMesh(unsigned int image_nr)
Definition: ViewState.cpp:420
bool RequireRecalculateMasks(unsigned int image_nr)
Definition: ViewState.cpp:304
const std::vector< double > & getProjectionParameters() const
Get the optional projection parameters.
bool RequireRecalculatePhotometric()
Definition: ViewState.cpp:294
virtual HuginBase::PanoramaOptions * GetOptions()
Definition: ViewState.cpp:468
virtual ~VisualizationState()
Definition: ViewState.cpp:366
static T max(T x, T y)
Definition: svm.cpp:65
void SetOptions(const HuginBase::PanoramaOptions *new_opts)
Definition: ViewState.cpp:120
#define DEBUG_DEBUG(msg)
Definition: utils.h:68
HuginBase::PanoramaOptions * GetOptions()
Definition: ViewState.cpp:620
TextureManager * m_tex_manager
Definition: ViewState.h:155
T simpleClipPoint(const T &point, const T &min, const T &max)
clip a point to fit int [min, max] does not do a mathematical clipping, just sets p...
Definition: hugin_math.h:158
bool RequireRecalculateImageSizes()
Definition: ViewState.cpp:289
OutputProjectionInfo * projection_info
Definition: ViewState.h:134
const SrcPanoImage & getImage(std::size_t nr) const
get a panorama image, counting starts with 0
Definition: Panorama.h:211
void panoramaImagesChanged(HuginBase::Panorama &, const HuginBase::UIntSet &)
notifies about changes to images
Definition: ViewState.cpp:114
bool ImagesRemoved()
Definition: ViewState.cpp:299
std::map< unsigned int, fbool > dirty_mask
Definition: ViewState.h:149
HuginBase::SrcPanoImage * GetSrcImage(unsigned int image_nr)
Definition: ViewState.cpp:283
All variables of a source image.
Definition: SrcPanoImage.h:194
void setProjection(ProjectionFormat f)
set the Projection format and adjust the hfov/vfov if nessecary
void SetDirtyViewport()
Definition: ViewState.h:249
Panorama image options.
#define M_PI
Definition: GaborFilter.cpp:34
void SetZoomLevel(const float new_zoom)
Definition: ViewState.cpp:483
unsigned int GetMeshDisplayList(unsigned int image_nr)
Definition: ViewState.cpp:462
vigra::Size2D getSize() const
get size of output image
std::map< VisualizationState *, bool > vis_states
Definition: ViewState.h:127
static T min(T x, T y)
Definition: svm.cpp:62
unsigned int number_of_images
Definition: ViewState.h:136
bool images_removed
Definition: ViewState.h:150
A wxWidget to display the fast preview.
Definition: GLViewer.h:51
std::map< unsigned int, HuginBase::SrcPanoImage > img_states
Definition: ViewState.h:132
OutputProjectionInfo * projection_info
Definition: ViewState.h:341
unsigned int GetDisplayList(unsigned int image_number) const
HuginBase::PanoramaOptions * GetOptions()
Definition: ViewState.cpp:548
void CheckUpdate()
Definition: MeshManager.cpp:71
ViewState(HuginBase::Panorama *pano, bool supportMultiTexture)
Definition: ViewState.cpp:32