ViewState.cpp

Go to the documentation of this file.
00001 // -*- c-basic-offset: 4 -*-
00002 
00024 #ifdef __WXMAC__
00025 #include "panoinc_WX.h"
00026 #include "panoinc.h"
00027 #endif
00028 
00029 #include "ViewState.h"
00030 #include "MeshManager.h"
00031 
00032 
00033 
00034 ViewState::ViewState(PT::Panorama *pano, bool supportMultiTexture)
00035 {
00036 
00037 
00038     m_pano = pano;
00039     m_multiTexture=supportMultiTexture;
00040     m_pano->addObserver(this);
00041     // we will need to update everything for this panorama.
00042     dirty_image_sizes = true;
00043     images_removed = true;
00044     number_of_images = m_pano->getNrOfImages();
00045     for (unsigned int img = 0; img < number_of_images; img++)
00046     {
00047         img_states[img] = m_pano->getSrcImage(img);
00048         dirty_mask[img].val = false;
00049     }
00050     opts = m_pano->getOptions();
00051     projection_info = new OutputProjectionInfo(&opts);
00052     // now set the texture manager up.
00053     m_tex_manager = new TextureManager(m_pano, this);
00054 }
00055 
00056 ViewState::~ViewState()
00057 {
00058     m_pano->removeObserver(this);
00059     delete projection_info;
00060     delete m_tex_manager;
00061 }
00062 
00063 
00064 void ViewState::panoramaChanged(HuginBase::PanoramaData &pano)
00065 {
00066 
00067     bool require_draw=false;
00068 
00069     // anything could have happened, check everything.
00070     HuginBase::PanoramaOptions new_opts  = m_pano->getOptions();
00071     SetOptions(&new_opts);
00072     unsigned int imgs = m_pano->getNrOfImages();
00073     for (unsigned int img = 0; img < imgs; img++)
00074     {
00075         HuginBase::SrcPanoImage new_image = m_pano->getSrcImage(img);
00076         SetSrcImage(img, &new_image);
00077         // has the enabled state changed in the preview?
00078         bool new_active = m_pano->getImage(img).getActive();
00079         if (new_active != active[img])
00080         {
00081             require_draw = true;
00082             active[img] = new_active;
00083         }
00084     }
00085     // has the number of images changed?
00086     if (imgs < number_of_images)
00087     {
00088         // we've lost some
00089         dirty_image_sizes = true;
00090         require_draw = true;
00091         images_removed = true;
00092     } else if (imgs > number_of_images)
00093     {
00094         // added images. Assume it doesn't affect the rest.
00095         dirty_image_sizes = true;
00096         require_draw = true;
00097         // FIXME more might need to be done, if the new images are not the last
00098         // ones in order of image number.
00099     }
00100     number_of_images = imgs;
00101 
00102     if (require_draw) {
00103         //refresh function is called in the respective VisualizationState callback
00104         for (std::map<VisualizationState*,bool>::iterator it = vis_states.begin() ; it != vis_states.end() ; it++) {
00105             DEBUG_DEBUG("PanoChanged - iterator before");
00106             if (it->second) {
00107                 DEBUG_DEBUG("PanoChanged - iterator after");
00108                 it->first->Redraw();
00109             }
00110         }
00111     }
00112 
00113 }
00114 
00115 void ViewState::panoramaImagesChanged(HuginBase::PanoramaData&,
00116                                       const HuginBase::UIntSet&)
00117 {
00118     // actually this stuff is handled by panoramaChanged.
00119 }
00120 
00121 void ViewState::SetOptions(const HuginBase::PanoramaOptions *new_opts)
00122 {
00123 
00124     bool dirty_projection = false;
00125 
00126     for (std::map<VisualizationState*,bool>::iterator it = vis_states.begin() ; it != vis_states.end() ; it++) {
00127 
00128         if (!(it->second)) continue;
00129         
00130         // compare the options
00131         if (   new_opts->getSize() != opts.getSize()
00132             || new_opts->getProjection() != opts.getProjection()
00133             || new_opts->getProjectionParameters() != opts.getProjectionParameters()
00134             || new_opts->getHFOV() != opts.getHFOV()
00135             || new_opts->getVFOV() != opts.getVFOV()
00136            )
00137         {
00138             // output projection changed. All images' meshes need recalculating.
00139             unsigned int imgs = m_pano->getNrOfImages();
00140             for (unsigned int img = 0; img < imgs; img++)
00141             {
00142                 it->first->SetDirtyMesh(img);
00143             }
00144             // we should also change the viewport to fit new the dimensions.
00145             dirty_projection = true;
00146             it->first->SetDirtyViewport();
00147             it->first->ForceRequireRedraw();
00148         }
00149         if (  new_opts->outputExposureValue != opts.outputExposureValue)
00150         {
00151             // output exposure changed. All image photometrics are now different.
00152             it->first->SetDirtyViewport();
00153             dirty_photometrics = true;
00154         }
00155         if (   new_opts->getROI() != opts.getROI()
00156            )
00157         {
00158             // this is all done every frame anyway.
00159             it->first->ForceRequireRedraw();
00160         }
00161 
00162         it->first->SetOptions(new_opts);
00163 
00164     }
00165     // store the new options
00166     opts = *new_opts;
00167     if (dirty_projection)
00168     {
00169         // we need to update the projection info as well.
00170         delete projection_info;
00171         projection_info = 0;
00172         projection_info = new OutputProjectionInfo(&opts);
00173     }
00174 }
00175 
00176 void ViewState::SetSrcImage(unsigned int image_nr, HuginBase::SrcPanoImage *new_img)
00177 {
00178     bool dirty_mesh = false;
00179     bool dirty_draw = false;
00180 
00181     if (number_of_images <= image_nr)
00182     {
00183         // this must be an addition, since we didn't have this many images.
00184         dirty_mesh = true;
00185         dirty_image_sizes = true;
00186         dirty_draw = true;
00187     } else {
00188         // compare the options
00189         HuginBase::SrcPanoImage *img = &img_states[image_nr];
00190         // if the filename has changed, something has probably been deleted
00191         if (new_img->getFilename() != img->getFilename())
00192         {
00193             images_removed = true;
00194             // since we use image numbers to identify meshes and images,
00195             // we can't really tell what happened.
00196         }
00197         // has the projection changed?
00198         if (   new_img->getRoll() != img->getRoll()
00199             || new_img->getPitch() != img->getPitch()
00200             || new_img->getYaw() != img->getYaw()
00201             || new_img->getX() != img->getX()
00202             || new_img->getY() != img->getY()
00203             || new_img->getZ() != img->getZ()
00204             || new_img->getHFOV() != img->getHFOV()
00205             || new_img->getProjection() != img->getProjection()
00206             || new_img->getShear() != img->getShear()
00207             || new_img->getRadialDistortionCenterShift()
00208                                        == img->getRadialDistortionCenterShift()
00209             || new_img->getRadialDistortion() != img->getRadialDistortion()
00210             || new_img->getCropRect() != img->getCropRect()
00211            )
00212         {
00213             dirty_mesh = true;
00214             dirty_draw = true;
00215 //            dirty_mesh[image_nr].val = true;
00216             // the field of view affects the image size calculations.
00217             if (new_img->getHFOV() != img->getHFOV())
00218             {
00219                 dirty_image_sizes = true;
00220             }
00221         }
00222         // photometric adjustments
00223         if (   new_img->getVigCorrMode() != img->getVigCorrMode()
00224             || new_img->getRadialVigCorrCoeff() != img->getRadialVigCorrCoeff()
00225             || new_img->getRadialVigCorrCenterShift() !=
00226                                               img->getRadialVigCorrCenterShift()
00227             || new_img->getExposureValue() != img->getExposureValue()
00228             || new_img->getGamma() != img->getGamma()
00229             || new_img->getWhiteBalanceRed() != img->getWhiteBalanceRed()
00230             || new_img->getWhiteBalanceBlue() != img->getWhiteBalanceBlue()
00231             || new_img->getResponseType() != img->getResponseType()
00232            )
00233         {
00234             // real time photometric correction just needs a redraw.
00235             /* full photometric correction will be redone automatically by the
00236                TextureManager next redraw.                                    */
00237             /* FIXME only white balance and exposure are actually used for
00238                real-time photometric correction. */
00239             dirty_draw = true;
00240         }
00241         // mask stuff
00242         if(new_img->getActiveMasks() != img->getActiveMasks())
00243         {
00244             dirty_mask[image_nr].val = true;
00245             dirty_draw=true;
00246         };
00247     }
00248     // store the new options
00249     img_states[image_nr] = *new_img;
00250 
00251 
00252     for (std::map<VisualizationState*,bool>::iterator it = vis_states.begin() ; it != vis_states.end() ; it++) {
00253         if (!(it->second)) continue;
00254         if (dirty_draw) it->first->ForceRequireRedraw();
00255         if (dirty_mesh) it->first->SetDirtyMesh(image_nr);
00256         it->first->SetSrcImage(image_nr, new_img);
00257     }
00258     
00259 }
00260 
00261 void ViewState::ForceRequireRedraw()
00262 {
00263     // this is generally called by preview tools. We let them manage themselves.
00264     // often they give some user interface thing that doesn't reflect a change
00265     // in the panorama at all, so we let them force a redraw.
00266     for (std::map<VisualizationState*,bool>::iterator it = vis_states.begin() ; it != vis_states.end() ; it++) {
00267         if (!(it->second)) continue;
00268         it->first->ForceRequireRedraw();
00269     }
00270 }
00271 
00272 
00273 HuginBase::PanoramaOptions *ViewState::GetOptions()
00274 {
00275     return &opts;
00276 }
00277 
00278 OutputProjectionInfo *ViewState::GetProjectionInfo()
00279 {
00280     return projection_info;
00281 }
00282 
00283 HuginBase::SrcPanoImage *ViewState::GetSrcImage(unsigned int image_nr)
00284 {
00285     return &img_states[image_nr];
00286 }
00287 
00288 
00289 bool ViewState::RequireRecalculateImageSizes()
00290 {
00291     return dirty_image_sizes;
00292 }
00293 
00294 bool ViewState::RequireRecalculatePhotometric()
00295 {
00296     return dirty_photometrics;
00297 }
00298 
00299 bool ViewState::ImagesRemoved()
00300 {
00301     return images_removed;
00302 }
00303 
00304 bool ViewState::RequireRecalculateMasks(unsigned int image_nr)
00305 {
00306     if (number_of_images > image_nr)
00307     {
00308         return dirty_mask[image_nr].val;
00309     }
00310     return false;
00311 }
00312 
00313 
00314 void ViewState::FinishedDraw()
00315 {
00316     // update our copy of the state and clear all the dirty flags.
00317     number_of_images = m_pano->getNrOfImages();
00318     img_states.clear();
00319     active.clear();
00320     for (unsigned int img = 0; img < number_of_images; img++)
00321     {
00322         img_states[img] = m_pano->getSrcImage(img);
00323         active[img] = m_pano->getImage(img).getActive();
00324     }
00325     opts = m_pano->getOptions();
00326     
00327     Clean();
00328 }
00329 
00330 void ViewState::Clean()
00331 {
00332     dirty_image_sizes = false;
00333     images_removed = false;
00334     dirty_photometrics = false;
00335     dirty_mask.clear();
00336 }
00337 
00338 void ViewState::DoUpdates()
00339 {
00340     DEBUG_DEBUG("VIEW STATE DO UPDATES");
00341     m_tex_manager->CheckUpdate();
00342     DEBUG_DEBUG("VIEW STATE END DO UPDATES");
00343 }
00344 
00345 void ViewState::Redraw()
00346 {
00347 
00348     for (std::map<VisualizationState*,bool>::iterator it = vis_states.begin() ; it != vis_states.end() ; it++) {
00349         
00350         if (!(it->second)) continue;
00351         
00352         it->first->Redraw();
00353         
00354     }
00355 
00356 
00357 }
00358 
00359 
00360 
00361 
00362 
00363 
00364 
00365 
00366 VisualizationState::~VisualizationState()
00367 {
00368     m_view_state->vis_states[this] = false;
00369     delete m_mesh_manager;
00370 }
00371 
00372 
00373 float VisualizationState::GetScale()
00374 {
00375     return scale;
00376 }
00377 
00378 void VisualizationState::SetScale(float scale_in)
00379 {
00380     scale = scale_in;
00381     // When resizing the window this can make the level detail of existing
00382     // meshes be too high or low, but we don't want to do to much calculation
00383     // so limit the forced recalculation of meshes to significant changes.
00384     if (genscale == 0.0)
00385     {
00386         // should only happen the first time it is used. In which case we will
00387         // regenerate the meshes anyways.
00388         genscale = scale;
00389     } else {
00390         double difference = scale > genscale ?
00391                scale / genscale : genscale / scale;
00392         if (difference > 1.25)
00393         {
00394             genscale = scale;
00395             unsigned int number_of_images = m_pano->getNrOfImages();
00396             for (unsigned int img = 0; img < number_of_images; img++)
00397             {
00398                 dirty_mesh[img].val = true;
00399             }        
00400         }
00401     }
00402 }
00403 
00404 
00405 void VisualizationState::Redraw()
00406 {
00407     DEBUG_DEBUG("REDRAW OUT");
00408     if (RequireDraw())
00409     {
00410         DEBUG_DEBUG("REDRAW IN");
00411         RefreshFunc(refreshArg);
00412     }
00413 }
00414 
00415 bool VisualizationState::RequireRecalculateViewport()
00416 {
00417     return dirty_viewport;
00418 }
00419 
00420 bool VisualizationState::RequireRecalculateMesh (unsigned int image_nr)
00421 {
00422 
00423     unsigned int number_of_images = m_pano->getNrOfImages();
00424     if (number_of_images > image_nr)
00425     {
00426         return dirty_mesh[image_nr].val;
00427     }
00428     // if we didn't think there were enough images, create the mesh for the
00429     //   first time
00430     return true;
00431 }
00432 
00433 
00434 bool VisualizationState::RequireDraw()
00435 {
00436     return (dirty_draw);
00437 }
00438 
00439 void VisualizationState::ForceRequireRedraw()
00440 {
00441     dirty_draw = true;
00442 }
00443 
00444 void VisualizationState::FinishedDraw()
00445 {
00446     DEBUG_DEBUG("VIS State Finished draw");
00447     dirty_mesh.clear();
00448     dirty_viewport = false;
00449     dirty_draw = false;
00450     m_view_state->FinishedDraw();
00451 }
00452 
00453 void VisualizationState::DoUpdates()
00454 {
00455     DEBUG_DEBUG("BEGIN UPDATES");
00456     m_view_state->DoUpdates();
00457     DEBUG_DEBUG("END UPDATES");
00458     m_mesh_manager->CheckUpdate();
00459     DEBUG_DEBUG("END UPDATES");
00460 }
00461 
00462 unsigned int VisualizationState::GetMeshDisplayList(unsigned int image_number)
00463 {
00464     return m_mesh_manager->GetDisplayList(image_number);
00465 }
00466 
00467 
00468 HuginBase::PanoramaOptions * VisualizationState::GetOptions()
00469 {
00470     return m_view_state->GetOptions();
00471 }
00472 
00473  OutputProjectionInfo * VisualizationState::GetProjectionInfo()
00474 {
00475     return m_view_state->GetProjectionInfo();
00476 }
00477 
00478 HuginBase::SrcPanoImage * VisualizationState::GetSrcImage(unsigned int image_nr)
00479 {
00480     return m_view_state->GetSrcImage(image_nr);
00481 }
00482 
00483 
00484 
00485 PanosphereOverviewVisualizationState::PanosphereOverviewVisualizationState(PT::Panorama* pano, ViewState* view_state, GLViewer * viewer, void (*RefreshFunction)(void*), void *arg)
00486         : OverviewVisualizationState(pano, view_state, viewer, RefreshFunction, arg, (PanosphereOverviewMeshManager*) NULL) 
00487 {
00488     scale = 1;
00489 
00490     angx = M_PI / 2.0;
00491     angy = 0;
00492     fov = 40;
00493     R = 500;
00494     sphere_radius = 100;
00495 
00496     opts = (*(m_view_state->GetOptions()));
00497     opts.setProjection(HuginBase::PanoramaOptions::EQUIRECTANGULAR);
00498     opts.setHFOV(360.0);
00499     opts.setVFOV(180.0);
00500     projection_info = new OutputProjectionInfo(&opts);
00501 }
00502 
00503 PanosphereOverviewVisualizationState::~PanosphereOverviewVisualizationState()
00504 {
00505     delete projection_info;
00506 }
00507 
00508 HuginBase::PanoramaOptions * PanosphereOverviewVisualizationState::GetOptions()
00509 {
00510     return &opts;
00511 }
00512 
00513 OutputProjectionInfo *PanosphereOverviewVisualizationState::GetProjectionInfo()
00514 {
00515     return projection_info;
00516 }
00517 
00518 void PanosphereOverviewVisualizationState::SetOptions(const HuginBase::PanoramaOptions * new_opts)
00519 {
00520     opts = *new_opts;
00521     opts.setProjection(HuginBase::PanoramaOptions::EQUIRECTANGULAR);
00522     opts.setHFOV(360.0);
00523     opts.setVFOV(180.0);
00524     delete projection_info;
00525     projection_info = new OutputProjectionInfo(&opts);
00526 }
00527 
00528 void PanosphereOverviewVisualizationState::setAngX(double angx_in)
00529 {
00530     angx = angx_in;
00531     dirty_draw = true;
00532 }
00533 
00534 void PanosphereOverviewVisualizationState::setAngY(double angy_in)
00535 {
00536     angy = angy_in;
00537     dirty_draw = true;
00538 }
00539 
00540 
00541 PlaneOverviewVisualizationState::PlaneOverviewVisualizationState(PT::Panorama* pano, ViewState* view_state, GLViewer * viewer, void (*RefreshFunction)(void*), void *arg)
00542         : OverviewVisualizationState(pano, view_state, viewer, RefreshFunction, arg, (PlaneOverviewMeshManager*) NULL) 
00543 {
00544 
00545     scale = 1;
00546 
00547     fov = 60;
00548     R = 500;
00549     X = 0;
00550     Y = 0;
00551 
00552     opts = (*(m_view_state->GetOptions()));
00553     opts.setProjection(HuginBase::PanoramaOptions::RECTILINEAR);
00554     //TODO: hfov and vfov need to be divided into values for the output and values for the visualization
00555     opts.setHFOV(90.0);
00556     opts.setVFOV(90.0);
00557     projection_info = new OutputProjectionInfo(&opts);
00558 }
00559 
00560 PlaneOverviewVisualizationState::~PlaneOverviewVisualizationState()
00561 {
00562     delete projection_info;
00563 }
00564 
00565 HuginBase::PanoramaOptions * PlaneOverviewVisualizationState::GetOptions()
00566 {
00567     return &opts;
00568 }
00569 
00570 OutputProjectionInfo *PlaneOverviewVisualizationState::GetProjectionInfo()
00571 {
00572     return projection_info;
00573 }
00574 
00575 void PlaneOverviewVisualizationState::SetOptions(const HuginBase::PanoramaOptions * new_opts)
00576 {
00577     opts = *new_opts;
00578     opts.setProjection(HuginBase::PanoramaOptions::RECTILINEAR);
00579     opts.setHFOV(90.0);
00580     opts.setVFOV(90.0);
00581     delete projection_info;
00582     projection_info = new OutputProjectionInfo(&opts);
00583 }
00584 
00585 

Generated on Wed Jul 16 01:25:36 2014 for Hugintrunk by  doxygen 1.3.9.1