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

Generated on 23 Jul 2016 for Hugintrunk by  doxygen 1.4.7