diff --git a/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/InstrumentActor.cpp b/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/InstrumentActor.cpp index 7ab6f4d3a17e492a721a9198f5a4af5ff8e40f20..7e7a128f0e8da3d462caa44e469e05c37a6793be 100644 --- a/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/InstrumentActor.cpp +++ b/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/InstrumentActor.cpp @@ -39,15 +39,16 @@ m_maskedColor(100,100,100), m_failedColor(200,200,200), m_sampleActor(NULL) { - if (!m_workspace) + auto shared_workspace = m_workspace.lock(); + if (!shared_workspace) throw std::logic_error("InstrumentActor passed a workspace that isn't a MatrixWorkspace"); - const size_t nHist = m_workspace->getNumberHistograms(); + const size_t nHist = shared_workspace->getNumberHistograms(); m_WkspBinMin = DBL_MAX; m_WkspBinMax = -DBL_MAX; for (size_t i = 0; i < nHist; ++i) { - const Mantid::MantidVec & values = m_workspace->readX(i); + const Mantid::MantidVec & values = shared_workspace->readX(i); double xtest = values.front(); if( xtest != std::numeric_limits<double>::infinity() ) { @@ -85,7 +86,7 @@ m_sampleActor(NULL) blockSignals(false); /// Cache a map (actually a vector) to workspace indexes. - m_workspace->getDetectorIDToWorkspaceIndexVector(m_id2wi_vector, m_id2wi_offset, false); + shared_workspace->getDetectorIDToWorkspaceIndexVector(m_id2wi_vector, m_id2wi_offset, false); // If the instrument is empty, maybe only having the sample and source if (getInstrument()->nelements() < 3) @@ -100,7 +101,7 @@ m_sampleActor(NULL) accept(findVisitor); const ObjComponentActor* samplePosActor = dynamic_cast<const ObjComponentActor*>(findVisitor.getActor()); - m_sampleActor = new SampleActor(*this,m_workspace->sample(),samplePosActor); + m_sampleActor = new SampleActor(*this,shared_workspace->sample(),samplePosActor); m_scene.addActor(m_sampleActor); } @@ -136,7 +137,14 @@ bool InstrumentActor::accept(const GLActorVisitor& visitor) */ MatrixWorkspace_const_sptr InstrumentActor::getWorkspace() const { - return m_workspace; + auto shared_workspace = m_workspace.lock(); + + if ( !shared_workspace ) + { + throw std::runtime_error("Instrument view: workspace doesn't exist"); + } + + return shared_workspace; } Instrument_const_sptr InstrumentActor::getInstrument() const @@ -147,20 +155,22 @@ Instrument_const_sptr InstrumentActor::getInstrument() const // to define our 'default' view std::string view = Mantid::Kernel::ConfigService::Instance().getString("instrument.view.geometry"); + auto shared_workspace = getWorkspace(); + if ( boost::iequals("Default", view) || boost::iequals("Physical", view)) { // First see if there is a 'physical' instrument available. Use it if there is. - retval = m_workspace->getInstrument()->getPhysicalInstrument(); + retval = shared_workspace->getInstrument()->getPhysicalInstrument(); } else if (boost::iequals("Neutronic", view)) { - retval = m_workspace->getInstrument(); + retval = shared_workspace->getInstrument(); } if ( ! retval ) { // Otherwise get hold of the 'main' instrument and use that - retval = m_workspace->getInstrument(); + retval = shared_workspace->getInstrument(); } return retval; @@ -272,7 +282,9 @@ void InstrumentActor::resetColors() QwtDoubleInterval qwtInterval(m_DataMinScaleValue,m_DataMaxScaleValue); m_colors.resize(m_specIntegrs.size()); - Instrument_const_sptr inst = m_workspace->getInstrument(); + auto shared_workspace = getWorkspace(); + + Instrument_const_sptr inst = shared_workspace->getInstrument(); //PARALLEL_FOR1(m_workspace) for (int iwi=0; iwi < int(m_specIntegrs.size()); iwi++) @@ -282,7 +294,7 @@ void InstrumentActor::resetColors() try { // Find if the detector is masked - const std::set<detid_t>& dets = m_workspace->getSpectrum(wi)->getDetectorIDs(); + const std::set<detid_t>& dets = shared_workspace->getSpectrum(wi)->getDetectorIDs(); bool masked = inst->isDetectorMasked(dets); if (masked) diff --git a/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/InstrumentActor.h b/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/InstrumentActor.h index 205e5786901629a5f1bb2d2a6e7a0ef89f3ff94a..ab88e2bd1e8188780af56779f357d42e5b543283 100644 --- a/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/InstrumentActor.h +++ b/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/InstrumentActor.h @@ -9,8 +9,8 @@ #include "MantidAPI/SpectraDetectorTypes.h" -#include <boost/shared_ptr.hpp> -#include <boost/scoped_ptr.hpp> +//#include <boost/shared_ptr.hpp> +#include <boost/weak_ptr.hpp> #include <vector> #include <map> @@ -125,7 +125,7 @@ protected: size_t push_back_detid(Mantid::detid_t)const; - const boost::shared_ptr<const Mantid::API::MatrixWorkspace> m_workspace; + const boost::weak_ptr<const Mantid::API::MatrixWorkspace> m_workspace; MantidColorMap m_colorMap; /// integrated spectra std::vector<double> m_specIntegrs; diff --git a/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/InstrumentWindow.cpp b/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/InstrumentWindow.cpp index 60820bb167fe97297b0dd27da3b49b3cad84476a..d4939eef6f4d91bc41e13d85c26f02582bcee678 100644 --- a/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/InstrumentWindow.cpp +++ b/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/InstrumentWindow.cpp @@ -63,6 +63,15 @@ public: void setSurface(ProjectionSurface* surface){m_surface = surface;} /// Return the surface ProjectionSurface* getSurface(){return m_surface;} + /// Refreshes the view + void refreshView() + { + if(m_surface) + { + m_surface->updateView(); + update(); + } + } protected: void paintEvent(QPaintEvent*) { @@ -807,7 +816,13 @@ void InstrumentWindow::afterReplaceHandle(const std::string& wsName, //Replace current workspace if (wsName == m_workspaceName.toStdString()) { - //updateWindow(); + if (m_instrumentActor) + { + saveSettings(); + delete m_instrumentActor; + } + init(); + updateWindow(); } } @@ -817,6 +832,17 @@ void InstrumentWindow::clearADSHandle() close(); } +void InstrumentWindow::updateWindow() +{ + if ( isGLEnabled() ) + { + m_InstrumentDisplay->refreshView(); + } + else + { + m_simpleDisplay->refreshView(); + } +} /** * This method saves the workspace name associated with the instrument window diff --git a/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/InstrumentWindowRenderTab.cpp b/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/InstrumentWindowRenderTab.cpp index b31831d0da18879b36dd6d2641986e9e756dd5c8..2d4552f505ccd1e09f4a06e6ea2d0d8266f4492f 100644 --- a/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/InstrumentWindowRenderTab.cpp +++ b/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/InstrumentWindowRenderTab.cpp @@ -14,6 +14,8 @@ #include <QSettings> #include <QAction> #include <QSignalMapper> +#include <QMessageBox> + #include <qwt_scale_widget.h> #include <qwt_scale_engine.h> @@ -35,9 +37,7 @@ QFrame(instrWindow),m_instrWindow(instrWindow) QStringList modeList; modeList << "Full 3D" << "Cylindrical X" << "Cylindrical Y" << "Cylindrical Z" << "Spherical X" << "Spherical Y" << "Spherical Z"; m_renderMode->insertItems(0,modeList); - connect(m_renderMode,SIGNAL(currentIndexChanged(int)),m_instrWindow,SLOT(setSurfaceType(int))); - connect(m_renderMode, SIGNAL(currentIndexChanged(int)), this, SLOT(showResetView(int))); - connect(m_renderMode, SIGNAL(currentIndexChanged(int)), this, SLOT(showFlipControl(int))); + connect(m_renderMode,SIGNAL(currentIndexChanged(int)), this, SLOT(setSurfaceType(int))); // Save image control mSaveImage = new QPushButton(tr("Save image")); @@ -269,10 +269,10 @@ void InstrumentWindowRenderTab::updateSurfaceTypeControl(int type) void InstrumentWindowRenderTab::flipUnwrappedView(bool on) { - UnwrappedSurface* surface = dynamic_cast<UnwrappedSurface*>(m_InstrumentDisplay->getSurface()); + UnwrappedSurface* surface = dynamic_cast<UnwrappedSurface*>(m_instrWindow->getSurface()); if (!surface) return; surface->setFlippedView(on); - m_InstrumentDisplay->refreshView(); + m_instrWindow->updateWindow(); } /** @@ -363,3 +363,23 @@ void InstrumentWindowRenderTab::displaySettingsAboutToshow() } } +/** + * Change the type of the surface. + * @param index :: Index selected in the surface type combo box. + */ +void InstrumentWindowRenderTab::setSurfaceType(int index) +{ + // don't allow the simple viewer with 3D mode + if ( index == InstrumentWindow::FULL3D && !m_instrWindow->isGLEnabled() ) + { + m_renderMode->blockSignals( true ); + m_renderMode->setCurrentIndex( m_instrWindow->getSurfaceType() ); + m_renderMode->blockSignals( false ); + QMessageBox::warning(this,"MantidPlot - Warning","OpenGL must be enabled to view the instrument in 3D.\n" + "Check \"Use OpenGL\" in Display Settings."); + return; + } + m_instrWindow->setSurfaceType( index ); + showResetView( index ); + showFlipControl( index ); +} diff --git a/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/InstrumentWindowRenderTab.h b/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/InstrumentWindowRenderTab.h index c011532a9c68f2cf53b58a5bbc6e2a6027c475a4..82942d6b490bada7d0baebd2a852c2835b1a5d87 100644 --- a/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/InstrumentWindowRenderTab.h +++ b/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/InstrumentWindowRenderTab.h @@ -52,6 +52,8 @@ private slots: void flipUnwrappedView(bool); /// Called before the display setting menu opens. Filters out menu options. void displaySettingsAboutToshow(); + /// Change the type of the surface + void setSurfaceType(int); private: void showEvent (QShowEvent *); QMenu* createPeaksMenu(); diff --git a/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/MantidGLWidget.cpp b/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/MantidGLWidget.cpp index 29bbe652bf10a6e0ab45361869f091f7335888db..bb3fd75671e1cc6d27b1b2795dd2813420de96cf 100644 --- a/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/MantidGLWidget.cpp +++ b/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/MantidGLWidget.cpp @@ -4,6 +4,7 @@ #include "MantidGLWidget.h" #include "OpenGLError.h" #include "UnwrappedSurface.h" +#include "Projection3D.h" #include <boost/shared_ptr.hpp> @@ -98,52 +99,11 @@ void MantidGLWidget::setRenderingOptions() //enablewriting into the depth buffer glDepthMask(GL_TRUE); - setLightingModel(1); + //setLightingModel(1); OpenGLError::check("setRenderingOptions"); } -/** - * Toggles the use of high resolution lighting - * @param state :: An integer indicating lighting state. - * 0 - no light - * 1 - GL_LIGHT0 is defined but lighting is off. Can be set on for individual actors. - * 2 - GL_LIGHT0 is always on. - */ -void MantidGLWidget::setLightingModel(int state) -{ - // Basic lighting - if( state == 0 ) - { - glShadeModel(GL_FLAT); - glDisable(GL_LIGHTING); - glDisable(GL_LIGHT0); - glDisable(GL_LINE_SMOOTH); - } - else// High end shading and lighting - { - glShadeModel(GL_SMOOTH); // Shade model is smooth (expensive but looks pleasing) - glEnable(GL_LIGHT0); // Enable opengl first light - glEnable(GL_LINE_SMOOTH); // Set line should be drawn smoothly - glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,GL_TRUE); // This model lits both sides of the triangle - // Set Light0 Attributes, Ambient, diffuse,specular and position - // Its a directional light which follows camera position - float lamp_ambient[4]={0.30f, 0.30f, 0.30f, 1.0f}; - float lamp_diffuse[4]={1.0f, 1.0f, 1.0f, 1.0f}; - float lamp_specular[4]={1.0f,1.0f,1.0f,1.0f}; - glLightfv(GL_LIGHT0, GL_AMBIENT,lamp_ambient ); - glLightfv(GL_LIGHT0, GL_DIFFUSE, lamp_diffuse); - glLightfv(GL_LIGHT0, GL_SPECULAR, lamp_specular); - float lamp_pos[4]={0.0f, 0.0f, 0.0f, 1.0f}; // spot light at the origin - glLightfv(GL_LIGHT0, GL_POSITION, lamp_pos); - if (state == 2) - { - glEnable (GL_LIGHTING); // Enable light - } - } -} - - /** * This is overridden function which is called by Qt when the widget needs to be repainted. */ @@ -344,14 +304,14 @@ void MantidGLWidget::resetWidget() */ void MantidGLWidget::enableLighting(bool on) { - m_lightingState = on? 2 : 0; - setLightingModel(m_lightingState); - //if (m_unwrappedSurface) - //{ - // m_unwrappedSurface->updateView(); - //} - refreshView(); - repaint(); + auto surface3D = dynamic_cast<Projection3D*>(m_surface); + + if (surface3D) + { + surface3D->enableLighting( on ); + refreshView(); + //repaint(); + } } void MantidGLWidget::draw() diff --git a/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/MantidGLWidget.h b/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/MantidGLWidget.h index dd3d93ca887ae11c0bbf416b054111ae0c3e6bd9..a91f33125ef79baccdbe0f4879622cbf4cc1257f 100644 --- a/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/MantidGLWidget.h +++ b/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/MantidGLWidget.h @@ -55,7 +55,6 @@ protected: void leaveEvent (QEvent*); private: void setRenderingOptions(); - void setLightingModel(int); //QColor m_bgColor; ///< Background color //PolygonMode m_polygonMode; ///< SOLID or WIREFRAME diff --git a/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/Projection3D.cpp b/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/Projection3D.cpp index 256772fadab3a96134c34119f65fc267c28aa9c1..e23726129fe3fe07451ab8b95eeedb0d77ea2302 100644 --- a/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/Projection3D.cpp +++ b/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/Projection3D.cpp @@ -38,29 +38,15 @@ using namespace Mantid::Geometry; Projection3D::Projection3D(const InstrumentActor* rootActor,int winWidth,int winHeight) :ProjectionSurface(rootActor,Mantid::Kernel::V3D(),Mantid::Kernel::V3D(0,0,1)), - //m_instrActor(*rootActor), m_viewport(new GLViewport), m_drawAxes(true), m_wireframe(false), - m_isKeyPressed(false) + m_isKeyPressed(false), + m_isLightingOn(false) { Instrument_const_sptr instr = rootActor->getInstrument(); - // Janik Zikovsky Feb 7, 2012: The following lines do nothing and are very slow. Why are they here? Commented them out. -// std::vector<IComponent_const_sptr> allComponents; -// instr->getChildren(allComponents,true); -// std::vector<ComponentID> nonDetectors; -// std::vector<IComponent_const_sptr>::const_iterator it = allComponents.begin(); -// for(; it != allComponents.end(); ++it) -// { -// IDetector_const_sptr det = boost::dynamic_pointer_cast<const IDetector>(*it); -// if (!det) -// { -// nonDetectors.push_back((*it)->getComponentID()); -// } -// } - m_viewport->resize(winWidth,winHeight); V3D minBounds,maxBounds; m_instrActor->getBoundingBox(minBounds,maxBounds); @@ -111,6 +97,8 @@ void Projection3D::drawSurface(MantidGLWidget*,bool picking)const glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } + setLightingModel(picking); + m_viewport->issueGL(); //glClearColor(GLclampf(bgColor.red()/255.0),GLclampf(bgColor.green()/255.0),GLclampf(bgColor.blue()/255.0),1.0); @@ -381,11 +369,6 @@ void Projection3D::getMaskedDetectors(QList<int>& dets)const if (pos.Z() < zmin || pos.Z() > zmax) continue; if (m_maskShapes.isMasked(pos.X(),pos.Y())) { - // Note JZ Feb 7, 2012: The following method finds width but does not use it. - // I'm not sure what it is for so I'm commenting it out, it presumably does nothing. -// BoundingBox bb; -// det->getBoundingBox(bb); -// V3D width = bb.width(); dets.push_back(int(id)); } } @@ -437,21 +420,9 @@ void Projection3D::componentSelected(Mantid::Geometry::ComponentID id) rot.rotate(minBounds); rot.rotate(maxBounds); - //std::cerr << minBounds << maxBounds << std::endl; - - // cannot get it right -// double znear = minBounds.Z(); -// double zfar = maxBounds.Z(); - //if (znear > zfar) - //{ - // std::swap(znear,zfar); - //} - m_viewport->setOrtho(minBounds.X(),maxBounds.X(), minBounds.Y(),maxBounds.Y(), -1000.,1000); - //0,1000.); - //znear,zfar); m_trackball->reset(); @@ -480,3 +451,46 @@ QRectF Projection3D::getSurfaceBounds()const m_viewport->getInstantProjection(xmin,xmax,ymin,ymax,zmin,zmax); return QRectF(QPointF(xmin,ymin),QPointF(xmax,ymax)); } + +/** + * Enable or disable lighting in non-picking mode + * @param on :: True for enabling, false for disabling. + */ +void Projection3D::enableLighting(bool on) +{ + m_isLightingOn = on; +} + +/** + * Define lighting of the scene + */ +void Projection3D::setLightingModel(bool picking) const +{ + // Basic lighting + if ( m_isLightingOn && !picking ) + { + glShadeModel(GL_SMOOTH); // Shade model is smooth (expensive but looks pleasing) + glEnable(GL_LIGHT0); // Enable opengl first light + glEnable(GL_LINE_SMOOTH); // Set line should be drawn smoothly + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,GL_TRUE); // This model lits both sides of the triangle + // Set Light0 Attributes, Ambient, diffuse,specular and position + // Its a directional light which follows camera position + float lamp_ambient[4]={0.30f, 0.30f, 0.30f, 1.0f}; + float lamp_diffuse[4]={1.0f, 1.0f, 1.0f, 1.0f}; + float lamp_specular[4]={1.0f,1.0f,1.0f,1.0f}; + glLightfv(GL_LIGHT0, GL_AMBIENT,lamp_ambient ); + glLightfv(GL_LIGHT0, GL_DIFFUSE, lamp_diffuse); + glLightfv(GL_LIGHT0, GL_SPECULAR, lamp_specular); + float lamp_pos[4]={0.0f, 0.0f, 0.0f, 1.0f}; // spot light at the origin + glLightfv(GL_LIGHT0, GL_POSITION, lamp_pos); + glEnable (GL_LIGHTING); // Enable light + } + else + { + glShadeModel(GL_FLAT); + glDisable(GL_LIGHTING); + glDisable(GL_LIGHT0); + glDisable(GL_LINE_SMOOTH); + } +} + diff --git a/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/Projection3D.h b/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/Projection3D.h index 01bacb2bf66f8913c018748e2a577c9f6aeb92e4..400a374ddf0bf6352c07586a2ee117e1e483f065 100644 --- a/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/Projection3D.h +++ b/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/Projection3D.h @@ -47,6 +47,7 @@ public: void setViewDirection(const QString& vd); void set3DAxesState(bool on); void setWireframe(bool on); + void enableLighting(bool on); virtual void componentSelected(Mantid::Geometry::ComponentID = NULL); virtual void getSelectedDetectors(QList<int>& dets); @@ -63,6 +64,7 @@ protected: virtual void wheelEventMove(QWheelEvent *); void drawAxes(double axis_length = 100.0)const; + void setLightingModel(bool picking)const; //const InstrumentActor& m_instrActor; GLTrackball* m_trackball; ///< Trackball for user interaction @@ -70,6 +72,7 @@ protected: bool m_drawAxes; bool m_wireframe; bool m_isKeyPressed; + bool m_isLightingOn; ///< Lighting on/off flag }; diff --git a/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/UnwrappedSurface.cpp b/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/UnwrappedSurface.cpp index 2a5224b2eea08ed958e8acb7fade1ab0f0fb6b0b..bc3f6a1b2885604cdba21b025e670a6bf69c4a69 100644 --- a/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/UnwrappedSurface.cpp +++ b/Code/Mantid/MantidPlot/src/Mantid/InstrumentWidget/UnwrappedSurface.cpp @@ -918,7 +918,16 @@ void UnwrappedSurface::drawSimpleToImage(QImage* image,bool picking)const if (!(m_viewRect.contains(udet.u-w, udet.v-h) || m_viewRect.contains(udet.u+w, udet.v+h))) continue; - int u = ( udet.u - m_viewRect.left() ) / dw; + int u = 0; + if ( !isFlippedView() ) + { + u = ( udet.u - m_viewRect.left() ) / dw; + } + else + { + u = vwidth - ( udet.u - m_viewRect.right() ) / dw; + } + int v = vheight - ( udet.v - m_viewRect.bottom() ) / dh; QColor color;