Hugin trunk 0.1
Loading...
Searching...
No Matches
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
33{
34
35
36 m_pano = pano;
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 }
51 // now set the texture manager up.
53}
54
56{
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.
71 unsigned int imgs = m_pano->getNrOfImages();
72 for (unsigned int img = 0; img < imgs; img++)
73 {
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()
132 || new_opts->getProjectionParameters() != opts.getProjectionParameters()
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) ||
149 (new_opts->outputRangeCompression != opts.outputRangeCompression))
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;
168 {
169 // we need to update the projection info as well.
170 delete projection_info;
171 projection_info = 0;
173 }
174}
175
177{
178 bool dirty_mesh = false;
179 bool dirty_draw = false;
180
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
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
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
277
282
287
288
293
298
300{
301 return images_removed;
302}
303
305{
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 }
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
371
372
374{
375 return scale;
376}
377
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
419
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
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
462unsigned int VisualizationState::GetMeshDisplayList(unsigned int image_number)
463{
464 return m_mesh_manager->GetDisplayList(image_number);
465}
466
467
472
477
482
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 };
515}
516
518{
520 // update center
522}
523
542
547
552
557
567
573
579
581{
582 // limit new fov to 5 - 140 deg
583 fov = std::max(std::min(newFOV, 140.0), 5.0);
584}
585
587{
589 {
590 // inside/outside view changed, reset fov
591 setFOV(40);
593 };
594}
595
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
619
624
629
639
640
#define M_PI
A wxWidget to display the fast preview.
Definition GLViewer.h:52
Panorama image options.
void setHFOV(double h, bool keepView=true)
set the horizontal field of view.
void setProjection(ProjectionFormat f)
set the Projection format and adjust the hfov/vfov if nessecary
const std::vector< double > & getProjectionParameters() const
Get the optional projection parameters.
const vigra::Rect2D & getROI() const
PanoramaOptions::ProjectionFormat getProjection() const
vigra::Size2D getSize() const
get size of output image
Model for a panorama.
Definition Panorama.h:153
const SrcPanoImage & getImage(std::size_t nr) const
get a panorama image, counting starts with 0
Definition Panorama.h:211
const PanoramaOptions & getOptions() const
returns the options for this panorama
Definition Panorama.h:481
void addObserver(PanoramaObserver *o)
add a panorama observer.
SrcPanoImage getSrcImage(unsigned imgNr) const
get a description of a source image
bool removeObserver(PanoramaObserver *observer)
remove a panorama observer.
std::size_t getNrOfImages() const
number of images.
Definition Panorama.h:205
All variables of a source image.
void CheckUpdate()
unsigned int GetDisplayList(unsigned int image_number) const
HuginBase::PanoramaOptions opts
Definition ViewState.h:340
PanosphereOverviewVisualizationState(HuginBase::Panorama *pano, ViewState *view_state, GLViewer *viewer, void(*RefreshFunction)(void *), void *arg)
HuginBase::PanoramaOptions * GetOptions()
OutputProjectionInfo * GetProjectionInfo()
OutputProjectionInfo * projection_info
Definition ViewState.h:341
void SetOptions(const HuginBase::PanoramaOptions *new_opts)
void setInsideView(bool insideView)
PlaneOverviewVisualizationState(HuginBase::Panorama *pano, ViewState *view_state, GLViewer *viewer, void(*RefreshFunction)(void *), void *arg)
OutputProjectionInfo * projection_info
Definition ViewState.h:376
OutputProjectionInfo * GetProjectionInfo()
HuginBase::PanoramaOptions * GetOptions()
void SetOptions(const HuginBase::PanoramaOptions *new_opts)
HuginBase::PanoramaOptions opts
Definition ViewState.h:375
std::map< unsigned int, fbool > dirty_mask
Definition ViewState.h:149
HuginBase::Panorama * m_pano
Definition ViewState.h:131
void DoUpdates()
TextureManager * m_tex_manager
Definition ViewState.h:155
bool RequireRecalculateMasks(unsigned int image_nr)
void SetSrcImage(unsigned int image_nr, HuginBase::SrcPanoImage *new_img)
std::map< unsigned int, bool > active
Definition ViewState.h:148
ViewState(HuginBase::Panorama *pano, bool supportMultiTexture)
Definition ViewState.cpp:32
void SetOptions(const HuginBase::PanoramaOptions *new_opts)
bool images_removed
Definition ViewState.h:150
OutputProjectionInfo * GetProjectionInfo()
bool dirty_image_sizes
Definition ViewState.h:150
void panoramaImagesChanged(HuginBase::Panorama &, const HuginBase::UIntSet &)
notifies about changes to images
void ForceRequireRedraw()
HuginBase::PanoramaOptions * GetOptions()
void Clean()
void panoramaChanged(HuginBase::Panorama &pano)
Notification about a Panorama change.
Definition ViewState.cpp:63
HuginBase::PanoramaOptions opts
Definition ViewState.h:133
bool m_multiTexture
Definition ViewState.h:156
HuginBase::SrcPanoImage * GetSrcImage(unsigned int image_nr)
void FinishedDraw()
unsigned int number_of_images
Definition ViewState.h:136
std::map< unsigned int, HuginBase::SrcPanoImage > img_states
Definition ViewState.h:132
bool dirty_photometrics
Definition ViewState.h:147
OutputProjectionInfo * projection_info
Definition ViewState.h:134
std::map< VisualizationState *, bool > vis_states
Definition ViewState.h:127
bool RequireRecalculatePhotometric()
bool RequireRecalculateImageSizes()
bool ImagesRemoved()
void Redraw()
void SetZoomLevel(const float new_zoom)
void SetViewingCenter(const hugin_utils::FDiff2D &center)
HuginBase::Panorama * m_pano
Definition ViewState.h:255
hugin_utils::FDiff2D m_lookAt
Definition ViewState.h:272
void SetScale(float scale)
std::map< unsigned int, fbool > dirty_mesh
Definition ViewState.h:267
ViewState * m_view_state
Definition ViewState.h:280
virtual HuginBase::PanoramaOptions * GetOptions()
void(* RefreshFunc)(void *)
Definition ViewState.h:275
vigra::Size2D m_canvasSize
Definition ViewState.h:274
virtual OutputProjectionInfo * GetProjectionInfo()
bool RequireRecalculateViewport()
unsigned int GetMeshDisplayList(unsigned int image_nr)
virtual HuginBase::SrcPanoImage * GetSrcImage(unsigned int image_nr)
virtual ~VisualizationState()
void SetDirtyViewport()
Definition ViewState.h:249
MeshManager * m_mesh_manager
Definition ViewState.h:279
void SetCanvasSize(const vigra::Size2D &canvasSize)
bool RequireRecalculateMesh(unsigned int image_nr)
#define DEBUG_DEBUG(msg)
Definition utils.h:68
std::set< unsigned int > UIntSet
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:170
include file for the hugin project
include file for the hugin project
std::vector< deghosting::BImagePtr > threshold(const std::vector< deghosting::FImagePtr > &inputImages, const double threshold, const uint16_t flags)
Threshold function used for creating alpha masks for images.
Definition threshold.h:41