Salome HOME
Unicode support: correct handling of unicode on GUI level
[modules/gui.git] / src / OCCViewer / OCCViewer_ViewWindow.cxx
old mode 100755 (executable)
new mode 100644 (file)
index 4ca9750..3f3217a
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
 //
 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
@@ -24,6 +24,7 @@
 // Author :
 
 #include "OCCViewer_ViewWindow.h"
+#include "OCCViewer_ViewFrame.h"
 #include "OCCViewer_ViewModel.h"
 #include "OCCViewer_ViewPort3d.h"
 #include "OCCViewer_ViewManager.h"
 #include "OCCViewer_AxialScaleDlg.h"
 #include "OCCViewer_CubeAxesDlg.h"
 #include "OCCViewer_ClippingDlg.h"
-
-#include <Basics_OCCTVersion.hxx>
+#include "OCCViewer_RayTracingDlg.h"
+#include "OCCViewer_EnvTextureDlg.h"
+#include "OCCViewer_LightSourceDlg.h"
+#include "OCCViewer_Utilities.h"
 
 #include <SUIT_Desktop.h>
 #include <SUIT_Session.h>
 #include <QtxMultiAction.h>
 #include <QtxRubberBand.h>
 
-#include <OpenGLUtils_FrameBuffer.h>
-
 #include <QPainter>
 #include <QTime>
 #include <QImage>
 #include <QKeyEvent>
 #include <QMouseEvent>
 #include <QApplication>
+#include <QActionGroup>
 #include <QMenu>
 
 #include <AIS_ListOfInteractive.hxx>
 
 #include <BRep_Tool.hxx>
 #include <BRepBndLib.hxx>
+#include <BRepGProp.hxx>
+#include <GProp_GProps.hxx>
 #include <TopoDS.hxx>
 
+#include <Graphic3d_SequenceOfHClipPlane.hxx>
+#include <Graphic3d_ClipPlane.hxx>
+#include <OpenGl_GraphicDriver.hxx>
+#include <OpenGLUtils_FrameBuffer.h>
+
 #include <Graphic3d_MapIteratorOfMapOfStructure.hxx>
 #include <Graphic3d_MapOfStructure.hxx>
 #include <Graphic3d_Structure.hxx>
 #include <Graphic3d_ExportFormat.hxx>
+#include <Graphic3d_StereoMode.hxx>
+#include <Graphic3d_RenderingParams.hxx>
 
-#include <Visual3d_View.hxx>
 #include <V3d_Plane.hxx>
 #include <V3d_Light.hxx>
 
 #include <gp_Dir.hxx>
 #include <gp_Pln.hxx>
+#include <gp_GTrsf.hxx>
 #include <TColgp_Array1OfPnt2d.hxx>
 
-#if OCC_VERSION_LARGE > 0x06060000 
-#include <Graphic3d_SequenceOfHClipPlane.hxx>
-#include <Graphic3d_ClipPlane.hxx>
-
-#endif
+#include <Image_PixMap.hxx>
 
 #include <Standard_Version.hxx>
 
 
 static QEvent* l_mbPressEvent = 0;
 
-#ifdef WIN32
-# include <QWindowsStyle>
-#endif
+//#ifdef WIN32
+//# include <QWindowsStyle>
+//#endif
 
+#ifdef __APPLE__
+#include <OpenGL/gl.h>
+#else
 #include <GL/gl.h>
+#endif
+
+// To avoid conflict between KeyPress from the X.h (define KeyPress 2)
+// and QEvent::KeyPress (qevent.h)
+#ifdef KeyPress
+#undef KeyPress
+#endif
+
+// Enable ray tracing features
+#define ENABLE_RAY_TRACING
 
 const char* imageZoomCursor[] = {
 "32 32 3 1",
@@ -229,12 +249,13 @@ OCCViewer_ViewWindow::OCCViewer_ViewWindow( SUIT_Desktop*     theDesktop,
   myModel = theModel;
   myRestoreFlag = 0;
   myEnableDrawMode = false;
+  myDrawRectEnabled = true;
   myDrawRect=false;
   updateEnabledDrawMode();
   myScalingDlg = 0;
   mySetRotationPointDlg = 0;
   myRectBand = 0;
-  
+
   IsSketcherStyle = false;
   myIsKeyFree = false;
 
@@ -246,9 +267,9 @@ OCCViewer_ViewWindow::OCCViewer_ViewWindow( SUIT_Desktop*     theDesktop,
   myPreselectionEnabled = true;
   mySelectionEnabled = true;
 
+  myCursorIsHand = false;
 
   clearViewAspects();
-  
 }
 
 /*!
@@ -270,8 +291,8 @@ void OCCViewer_ViewWindow::initLayout()
   setCentralWidget(myViewPort);
   myOperation = NOTHING;
 
-  myCurrPointType = GRAVITY;
-  myPrevPointType = GRAVITY;
+  myCurrPointType = BBCENTER;
+  myPrevPointType = BBCENTER;
   mySelectedPoint = gp_Pnt(0.,0.,0.);
   myRotationPointSelection = false;
 
@@ -297,7 +318,7 @@ void OCCViewer_ViewWindow::initLayout()
   QtxAction* anAction = dynamic_cast<QtxAction*>( toolMgr()->action( GraduatedAxesId ) );
   myCubeAxesDlg = new OCCViewer_CubeAxesDlg( anAction, this, "OCCViewer_CubeAxesDlg" );
   myCubeAxesDlg->initialize();
-  
+
   connect( myViewPort, SIGNAL( vpTransformed( OCCViewer_ViewPort* ) ), this, SLOT( emitViewModified() ) );
 }
 
@@ -361,13 +382,28 @@ bool OCCViewer_ViewWindow::eventFilter( QObject* watched, QEvent* e )
     case QEvent::Wheel:
       {
         QWheelEvent* aEvent = (QWheelEvent*) e;
-  myViewPort->startZoomAtPoint( aEvent->x(), aEvent->y() );
-  double delta = (double)( aEvent->delta() ) / ( 15 * 8 );
-  int x  = aEvent->x();
-  int y  = aEvent->y();
-  int x1 = (int)( aEvent->x() + width()*delta/100 );
-  int y1 = (int)( aEvent->y() + height()*delta/100 );
-  myViewPort->zoom( x, y, x1, y1 );
+
+        if ( aEvent->modifiers().testFlag(Qt::ControlModifier) ) {
+          Handle(AIS_InteractiveContext) ic = myModel->getAISContext();
+          if ( isPreselectionEnabled() && myModel->useLocalSelection() ) {
+            if ( aEvent->delta() > 0 ) {
+              ic->HilightNextDetected( myViewPort->getView() );
+            } else {
+              ic->HilightPreviousDetected( myViewPort->getView() );
+            }
+          }
+        }
+        else {
+          emit vpTransformationStarted ( ZOOMVIEW );
+          myViewPort->startZoomAtPoint( aEvent->x(), aEvent->y() );
+          double delta = (double)( aEvent->delta() ) / ( 15 * 8 );
+          int x  = aEvent->x();
+          int y  = aEvent->y();
+          int x1 = (int)( aEvent->x() + width()*delta/100 );
+          int y1 = (int)( aEvent->y() + height()*delta/100 );
+          myViewPort->zoom( x, y, x1, y1 );
+          emit vpTransformationFinished ( ZOOMVIEW );
+        }
       }
       return true;
 
@@ -390,13 +426,25 @@ bool OCCViewer_ViewWindow::eventFilter( QObject* watched, QEvent* e )
   return SUIT_ViewWindow::eventFilter(watched, e);
 }
 
+/*!
+  \brief Enable / disable draw rect (rubber band) mode
+*/
+bool OCCViewer_ViewWindow::enableDrawMode( bool on )
+{
+  bool prev = myDrawRectEnabled;
+  myDrawRectEnabled = on;
+  updateEnabledDrawMode();
+  return prev;
+}
+
 /*!
   \brief Update state of enable draw mode state.
 */
 void OCCViewer_ViewWindow::updateEnabledDrawMode()
 {
+  myEnableDrawMode = myDrawRectEnabled;
   if ( myModel )
-    myEnableDrawMode = myModel->isSelectionEnabled() && myModel->isMultiSelectionEnabled();
+    myEnableDrawMode = myEnableDrawMode && myModel->isSelectionEnabled() && myModel->isMultiSelectionEnabled();
 }
 
 /*!
@@ -410,10 +458,10 @@ void OCCViewer_ViewWindow::vpMousePressEvent( QMouseEvent* theEvent )
   int anInteractionStyle = interactionStyle();
 
   // in "key free" interaction style zoom operation is activated by two buttons (simultaneously pressed),
-  // which are assigned for pan and rotate - these operations are activated immediately after pressing 
+  // which are assigned for pan and rotate - these operations are activated immediately after pressing
   // of the first button, so it is necessary to switch to zoom when the second button is pressed
   bool aSwitchToZoom = false;
-  if ( anInteractionStyle == SUIT_ViewModel::KEY_FREE && 
+  if ( anInteractionStyle == SUIT_ViewModel::KEY_FREE &&
        ( myOperation == PANVIEW || myOperation == ROTATE ) ) {
     aSwitchToZoom = getButtonState( theEvent, anInteractionStyle ) == ZOOMVIEW;
   }
@@ -483,28 +531,46 @@ void OCCViewer_ViewWindow::vpMousePressEvent( QMouseEvent* theEvent )
         if ( theEvent->button() == Qt::LeftButton )
         {
           Handle(AIS_InteractiveContext) ic = myModel->getAISContext();
-          ic->Select();
+          ic->Select( Standard_True );
           for ( ic->InitSelected(); ic->MoreSelected(); ic->NextSelected() )
           {
             TopoDS_Shape aShape = ic->SelectedShape();
+            GProp_GProps aSystem;
+            gp_Pnt aPnt;
             if ( !aShape.IsNull() && aShape.ShapeType() == TopAbs_VERTEX )
             {
-              gp_Pnt aPnt = BRep_Tool::Pnt( TopoDS::Vertex( ic->SelectedShape() ) );
-              if ( mySetRotationPointDlg )
-              {
-                myRotationPointSelection = false;
-                mySetRotationPointDlg->setCoords(aPnt.X(), aPnt.Y(), aPnt.Z());
-              }
+              aPnt = BRep_Tool::Pnt( TopoDS::Vertex( aShape ) );
+            }
+            else if ( !aShape.IsNull() && aShape.ShapeType() == TopAbs_EDGE )
+            {
+              BRepGProp::LinearProperties( aShape, aSystem );
+              aPnt = aSystem.CentreOfMass();
+            }
+            else if ( !aShape.IsNull() && aShape.ShapeType() == TopAbs_FACE )
+            {
+              BRepGProp::SurfaceProperties( aShape, aSystem );
+              aPnt = aSystem.CentreOfMass();
+            }
+            else if ( !aShape.IsNull() && aShape.ShapeType() == TopAbs_SOLID )
+            {
+              BRepGProp::VolumeProperties( aShape, aSystem );
+              aPnt = aSystem.CentreOfMass();
             }
             else
             {
               myCurrPointType = myPrevPointType;
               break;
             }
+
+            if ( mySetRotationPointDlg )
+            {
+              myRotationPointSelection = false;
+              mySetRotationPointDlg->setCoords(aPnt.X(), aPnt.Y(), aPnt.Z());
+            }
           }
           if ( ic->NbSelected() == 0 ) myCurrPointType = myPrevPointType;
           if ( mySetRotationPointDlg ) mySetRotationPointDlg->toggleChange();
-          ic->CloseAllContexts();
+          ic->CloseAllContexts( Standard_True );
           myOperation = NOTHING;
           myViewPort->setCursor( myCursor );
           myCursorIsHand = false;
@@ -517,7 +583,7 @@ void OCCViewer_ViewWindow::vpMousePressEvent( QMouseEvent* theEvent )
     }
     /* notify that we start a transformation */
     if ( transformRequested() )
-            emit vpTransformationStarted ( myOperation );
+      emit vpTransformationStarted ( myOperation );
   }
   if ( transformRequested() )
     setTransformInProcess( true );
@@ -537,7 +603,7 @@ void OCCViewer_ViewWindow::vpMousePressEvent( QMouseEvent* theEvent )
 void OCCViewer_ViewWindow::activateZoom()
 {
   if ( !transformRequested() && !myCursorIsHand )
-    myCursor = cursor();                /* save old cursor */
+    saveCursor();                /* save old cursor */
 
   if ( myOperation != ZOOMVIEW ) {
     QPixmap zoomPixmap (imageZoomCursor);
@@ -556,7 +622,7 @@ void OCCViewer_ViewWindow::activateZoom()
 void OCCViewer_ViewWindow::activatePanning()
 {
   if ( !transformRequested() && !myCursorIsHand )
-    myCursor = cursor();                // save old cursor
+    saveCursor();                // save old cursor
 
   if ( myOperation != PANVIEW ) {
     QCursor panCursor (Qt::SizeAllCursor);
@@ -573,7 +639,7 @@ void OCCViewer_ViewWindow::activatePanning()
 void OCCViewer_ViewWindow::activateRotation()
 {
   if ( !transformRequested() && !myCursorIsHand )
-    myCursor = cursor();                // save old cursor
+    saveCursor();                // save old cursor
 
   if ( myOperation != ROTATE ) {
     QPixmap rotatePixmap (imageRotateCursor);
@@ -592,69 +658,83 @@ void OCCViewer_ViewWindow::activateRotation()
 */
 bool OCCViewer_ViewWindow::computeGravityCenter( double& theX, double& theY, double& theZ )
 {
-  Handle(Visual3d_View) aView = myViewPort->getView()->View();
+  Handle(V3d_View) aView3d = myViewPort->getView();
 
-  Standard_Real Xmin,Ymin,Zmin,Xmax,Ymax,Zmax,U,V,W ;
-  Standard_Real Umin,Vmin,Umax,Vmax ;
-  Standard_Integer Nstruct,Npoint ;
-  Graphic3d_MapOfStructure MySetOfStructures;
+  // Project boundaries points and add to avergae gravity
+  // the ones which lie within the screen limits
+  Standard_Real aScreenLimits[4] = { 0.0, 0.0, 0.0, 0.0 };
+
+  // NDC space screen limits
+  aScreenLimits[0] = -1.0;
+  aScreenLimits[1] =  1.0;
+  aScreenLimits[2] = -1.0;
+  aScreenLimits[3] =  1.0;
+
+  Standard_Integer aPointsNb = 0;
+
+  Standard_Real aXmin = 0.0;
+  Standard_Real aYmin = 0.0;
+  Standard_Real aZmin = 0.0;
+  Standard_Real aXmax = 0.0;
+  Standard_Real aYmax = 0.0;
+  Standard_Real aZmax = 0.0;
+
+  Graphic3d_MapOfStructure aSetOfStructures;
+  aView3d->View()->DisplayedStructures( aSetOfStructures );
+  Graphic3d_MapIteratorOfMapOfStructure aStructureIt( aSetOfStructures );
+
+  for( ; aStructureIt.More(); aStructureIt.Next() ) {
+    const Handle(Graphic3d_Structure)& aStructure = aStructureIt.Key();
+    if ( aStructure->IsEmpty() || !aStructure->IsVisible() || aStructure->CStructure()->IsForHighlight )
+      continue;
+
+    Bnd_Box aBox = aStructure->MinMaxValues();
+    aXmin = aBox.IsVoid() ? RealFirst() : aBox.CornerMin().X();
+    aYmin = aBox.IsVoid() ? RealFirst() : aBox.CornerMin().Y();
+    aZmin = aBox.IsVoid() ? RealFirst() : aBox.CornerMin().Z();
+    aXmax = aBox.IsVoid() ? RealLast()  : aBox.CornerMax().X();
+    aYmax = aBox.IsVoid() ? RealLast()  : aBox.CornerMax().Y();
+    aZmax = aBox.IsVoid() ? RealLast()  : aBox.CornerMax().Z();
+
+    // Infinite structures are skipped
+    Standard_Real aLIM = ShortRealLast() - 1.0;
+    if ( Abs( aXmin ) > aLIM || Abs( aYmin ) > aLIM || Abs( aZmin ) > aLIM
+      || Abs( aXmax ) > aLIM || Abs( aYmax ) > aLIM || Abs( aZmax ) > aLIM ) {
+      continue;
+    }
 
-  aView->DisplayedStructures (MySetOfStructures);
-  Nstruct = MySetOfStructures.Extent() ;
+    gp_Pnt aPoints[8] = {
+      gp_Pnt( aXmin, aYmin, aZmin ), gp_Pnt( aXmin, aYmin, aZmax ),
+      gp_Pnt( aXmin, aYmax, aZmin ), gp_Pnt( aXmin, aYmax, aZmax ),
+      gp_Pnt( aXmax, aYmin, aZmin ), gp_Pnt( aXmax, aYmin, aZmax ),
+      gp_Pnt( aXmax, aYmax, aZmin ), gp_Pnt( aXmax, aYmax, aZmax )
+    };
 
-  Graphic3d_MapIteratorOfMapOfStructure MyIterator(MySetOfStructures) ;
-#if OCC_VERSION_LARGE > 0x06070000
-  aView->Camera()->WindowLimit(Umin,Vmin,Umax,Vmax);
-#else
-  aView->ViewMapping().WindowLimit(Umin,Vmin,Umax,Vmax);
-#endif
-  Npoint = 0 ; theX = theY = theZ = 0. ;
-  for( ; MyIterator.More(); MyIterator.Next()) {
-    if (!(MyIterator.Key())->IsEmpty()) {
-      (MyIterator.Key())->MinMaxValues(Xmin,Ymin,Zmin,
-                                         Xmax,Ymax,Zmax) ;
-
-      Standard_Real LIM = ShortRealLast() -1.;
-      if (!    (fabs(Xmin) > LIM || fabs(Ymin) > LIM || fabs(Zmin) > LIM
-                ||  fabs(Xmax) > LIM || fabs(Ymax) > LIM || fabs(Zmax) > LIM )) {
-
-        aView->Projects(Xmin,Ymin,Zmin,U,V,W) ;
-        if( U >= Umin && U <= Umax && V >= Vmin && V <= Vmax ) {
-          Npoint++ ; theX += Xmin ; theY += Ymin ; theZ += Zmin ;
-        }
-        aView->Projects(Xmax,Ymin,Zmin,U,V,W) ;
-        if( U >= Umin && U <= Umax && V >= Vmin && V <= Vmax ) {
-          Npoint++ ; theX += Xmax ; theY += Ymin ; theZ += Zmin ;
-        }
-        aView->Projects(Xmin,Ymax,Zmin,U,V,W) ;
-        if( U >= Umin && U <= Umax && V >= Vmin && V <= Vmax ) {
-          Npoint++ ; theX += Xmin ; theY += Ymax ; theZ += Zmin ;
-        }
-        aView->Projects(Xmax,Ymax,Zmin,U,V,W) ;
-        if( U >= Umin && U <= Umax && V >= Vmin && V <= Vmax ) {
-          Npoint++ ; theX += Xmax ; theY += Ymax ; theZ += Zmin ;
-        }
-        aView->Projects(Xmin,Ymin,Zmax,U,V,W) ;
-        if( U >= Umin && U <= Umax && V >= Vmin && V <= Vmax ) {
-          Npoint++ ; theX += Xmin ; theY += Ymin ; theZ += Zmax ;
-        }
-        aView->Projects(Xmax,Ymin,Zmax,U,V,W) ;
-        if( U >= Umin && U <= Umax && V >= Vmin && V <= Vmax ) {
-          Npoint++ ; theX += Xmax ; theY += Ymin ; theZ += Zmax ;
-        }
-        aView->Projects(Xmin,Ymax,Zmax,U,V,W) ;
-        if( U >= Umin && U <= Umax && V >= Vmin && V <= Vmax ) {
-          Npoint++ ; theX += Xmin ; theY += Ymax ; theZ += Zmax ;
-        }
-        aView->Projects(Xmax,Ymax,Zmax,U,V,W) ;
-        if( U >= Umin && U <= Umax && V >= Vmin && V <= Vmax ) {
-          Npoint++ ; theX += Xmax ; theY += Ymax ; theZ += Zmax ;
-        }
+    for ( Standard_Integer aPointIt = 0; aPointIt < 8; ++aPointIt ) {
+      const gp_Pnt& aBBPoint = aPoints[aPointIt];
+
+      gp_Pnt aProjected = aView3d->Camera()->Project( aBBPoint );
+      const Standard_Real& U = aProjected.X();
+      const Standard_Real& V = aProjected.Y();
+
+      if (U >= aScreenLimits[0]
+       && U <= aScreenLimits[1]
+       && V >= aScreenLimits[2]
+       && V <= aScreenLimits[3])
+      {
+        aPointsNb++;
+        theX += aBBPoint.X();
+        theY += aBBPoint.Y();
+        theZ += aBBPoint.Z();
       }
     }
   }
-  if( Npoint > 0 ) {
-    theX /= Npoint ; theY /= Npoint ; theZ /= Npoint ;
+
+  if ( aPointsNb > 0 )
+  {
+    theX /= aPointsNb;
+    theY /= aPointsNb;
+    theZ /= aPointsNb;
   }
   return true;
 }
@@ -667,7 +747,7 @@ void OCCViewer_ViewWindow::activateSetRotationGravity()
   if ( myRotationPointSelection )
   {
     Handle(AIS_InteractiveContext) ic = myModel->getAISContext();
-    ic->CloseAllContexts();
+    ic->CloseAllContexts( Standard_True );
     myOperation = NOTHING;
     myViewPort->setCursor( myCursor );
     myCursorIsHand = false;
@@ -675,10 +755,10 @@ void OCCViewer_ViewWindow::activateSetRotationGravity()
   }
 
   myPrevPointType = myCurrPointType;
-  myCurrPointType = GRAVITY;
+  myCurrPointType = BBCENTER;
 
   Standard_Real Xcenter, Ycenter, Zcenter;
-  if ( computeGravityCenter( Xcenter, Ycenter, Zcenter ) )
+  if ( OCCViewer_Utilities::computeVisibleBBCenter( myViewPort->getView(), Xcenter, Ycenter, Zcenter ) )
     mySetRotationPointDlg->setCoords( Xcenter, Ycenter, Zcenter );
 }
 
@@ -688,10 +768,10 @@ void OCCViewer_ViewWindow::activateSetRotationGravity()
 */
 void OCCViewer_ViewWindow::updateGravityCoords()
 {
-  if ( mySetRotationPointDlg && mySetRotationPointDlg->isVisible() && myCurrPointType == GRAVITY )
+  if ( mySetRotationPointDlg && mySetRotationPointDlg->isVisible() && myCurrPointType == BBCENTER )
   {
     Standard_Real Xcenter, Ycenter, Zcenter;
-    if ( computeGravityCenter( Xcenter, Ycenter, Zcenter ) )
+    if ( OCCViewer_Utilities::computeVisibleBBCenter( myViewPort->getView(), Xcenter, Ycenter, Zcenter ) )
       mySetRotationPointDlg->setCoords( Xcenter, Ycenter, Zcenter );
   }
 }
@@ -707,7 +787,7 @@ void OCCViewer_ViewWindow::activateSetRotationSelected( double theX, double theY
   if ( myRotationPointSelection )
   {
     Handle(AIS_InteractiveContext) ic = myModel->getAISContext();
-    ic->CloseAllContexts();
+    ic->CloseAllContexts( Standard_True );
     myOperation = NOTHING;
     myViewPort->setCursor( myCursor );
     myCursorIsHand = false;
@@ -720,9 +800,9 @@ void OCCViewer_ViewWindow::activateSetRotationSelected( double theX, double theY
 }
 
 /*!
-  \brief Start the point selection process.
+  \brief Start the shape selection process.
 */
-void OCCViewer_ViewWindow::activateStartPointSelection()
+void OCCViewer_ViewWindow::activateStartPointSelection( TopAbs_ShapeEnum theShapeType )
 {
   myPrevPointType = myCurrPointType;
   myCurrPointType = SELECTED;
@@ -741,7 +821,7 @@ void OCCViewer_ViewWindow::activateStartPointSelection()
          anObj->IsKind( STANDARD_TYPE(AIS_Shape) ) )
     {
       ic->Load(anObj,-1);
-      ic->Activate(anObj,AIS_Shape::SelectionMode(TopAbs_VERTEX));
+      ic->Activate(anObj,AIS_Shape::SelectionMode(theShapeType));
      }
   }
   // activate selection <------
@@ -750,7 +830,7 @@ void OCCViewer_ViewWindow::activateStartPointSelection()
   {
     QCursor handCursor (Qt::PointingHandCursor);
     myCursorIsHand = true;
-    myCursor = cursor();
+    saveCursor();
     myViewPort->setCursor( handCursor );
   }
   myRotationPointSelection = true;
@@ -769,7 +849,7 @@ void OCCViewer_ViewWindow::activateGlobalPanning()
     QCursor glPanCursor (globalPanPixmap);
     myCurScale = aView3d->Scale();
     aView3d->FitAll(0.01, false);
-    myCursor = cursor();                // save old cursor
+    saveCursor();                // save old cursor
     myViewPort->fitAll(); // fits view before selecting a new scene center
     if( setTransformRequested( PANGLOBAL ) )
       myViewPort->setCursor( glPanCursor );
@@ -784,7 +864,7 @@ void OCCViewer_ViewWindow::activateGlobalPanning()
 void OCCViewer_ViewWindow::activateWindowFit()
 {
   if ( !transformRequested() && !myCursorIsHand )
-    myCursor = cursor();                /* save old cursor */
+    saveCursor();                /* save old cursor */
 
   if ( myOperation != WINDOWFIT ) {
     QCursor handCursor (Qt::PointingHandCursor);
@@ -803,7 +883,7 @@ bool OCCViewer_ViewWindow::setTransformRequested( OperationType op )
 {
   bool ok = transformEnabled( op );
   myOperation = ok ? op : NOTHING;
-  myViewPort->setMouseTracking( myOperation == NOTHING );  
+  myViewPort->setMouseTracking( myOperation == NOTHING );
   return ok;
 }
 
@@ -879,7 +959,7 @@ void OCCViewer_ViewWindow::vpMouseMoveEvent( QMouseEvent* theEvent )
           if ( !myCursorIsHand )        {   // we are going to sketch a rectangle
             QCursor handCursor (Qt::PointingHandCursor);
             myCursorIsHand = true;
-            myCursor = cursor();
+            saveCursor();
             myViewPort->setCursor( handCursor );
           }
         }
@@ -1038,7 +1118,7 @@ void OCCViewer_ViewWindow::drawRect()
     //myRectBand->setPalette(palette);
   }
   //myRectBand->hide();
-  
+
   myRectBand->setUpdatesEnabled ( false );
   QRect aRect = SUIT_Tools::makeRect(myStartX, myStartY, myCurrX, myCurrY);
   myRectBand->initGeometry( aRect );
@@ -1078,8 +1158,10 @@ void OCCViewer_ViewWindow::createActions()
 {
   if( !toolMgr()->isEmpty() )
     return;
-  
+
   SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr();
+  if( !aResMgr )
+    return;
 
   QtxAction* aAction;
 
@@ -1103,7 +1185,14 @@ void OCCViewer_ViewWindow::createActions()
   aAction->setStatusTip(tr("DSC_FITRECT"));
   connect(aAction, SIGNAL(triggered()), this, SLOT(activateWindowFit()));
   toolMgr()->registerAction( aAction, FitRectId );
-  
+
+  // FitSelection
+  aAction = new QtxAction(tr("MNU_FITSELECTION"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_VIEW_FITSELECTION" ) ),
+                           tr( "MNU_FITSELECTION" ), 0, this);
+  aAction->setStatusTip(tr("DSC_FITSELECTION"));
+  connect(aAction, SIGNAL(triggered()), this, SLOT(onFitSelection()));
+  toolMgr()->registerAction( aAction, FitSelectionId );
+
   // Zoom
   aAction = new QtxAction(tr("MNU_ZOOM_VIEW"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_VIEW_ZOOM" ) ),
                            tr( "MNU_ZOOM_VIEW" ), 0, this);
@@ -1168,7 +1257,7 @@ void OCCViewer_ViewWindow::createActions()
   connect(aAction, SIGNAL(triggered()), this, SLOT(onBottomView()));
   this->addAction(aAction);
   toolMgr()->registerAction( aAction, BottomId );
-  
+
   aAction = new QtxAction(tr("MNU_LEFT_VIEW"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_VIEW_LEFT" ) ),
                            tr( "MNU_LEFT_VIEW" ), 0, this, false, "Viewers:Left view");
   aAction->setStatusTip(tr("DSC_LEFT_VIEW"));
@@ -1199,6 +1288,36 @@ void OCCViewer_ViewWindow::createActions()
   this->addAction(aAction);
   toolMgr()->registerAction( aAction, ClockWiseId );
 
+  // Projection mode group
+
+  // - orthographic projection
+  aAction = new QtxAction(tr("MNU_ORTHOGRAPHIC_MODE"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_ORTHOGRAPHIC" ) ),
+                          tr( "MNU_ORTHOGRAPHIC_MODE" ), 0, this);
+  aAction->setStatusTip(tr("DSC_ORTHOGRAPHIC_MODE"));
+  aAction->setCheckable(true);
+  toolMgr()->registerAction( aAction, OrthographicId );
+
+  // - perspective projection
+  aAction = new QtxAction(tr("MNU_PERSPECTIVE_MODE"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_PERSPECTIVE" ) ),
+                          tr( "MNU_PERSPECTIVE_MODE" ), 0, this);
+  aAction->setStatusTip(tr("DSC_PERSPECTIVE_MODE"));
+  aAction->setCheckable(true);
+  toolMgr()->registerAction( aAction, PerspectiveId );
+
+  // - stereo projection
+  aAction = new QtxAction(tr("MNU_STEREO_MODE"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_STEREO" ) ),
+                          tr( "MNU_STEREO_MODE" ), 0, this);
+  aAction->setStatusTip(tr("DSC_STEREO_MODE"));
+  aAction->setCheckable(true);
+  toolMgr()->registerAction( aAction, StereoId );
+  connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onStereoType(bool)));
+
+  // - add exclusive action group
+  QActionGroup* aProjectionGroup = new QActionGroup( this );
+  aProjectionGroup->addAction( toolMgr()->action( OrthographicId ) );
+  aProjectionGroup->addAction( toolMgr()->action( PerspectiveId ) );
+  connect(aProjectionGroup, SIGNAL(triggered(QAction*)), this, SLOT(onProjectionType(QAction*)));
+  
   // Reset
   aAction = new QtxAction(tr("MNU_RESET_VIEW"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_VIEW_RESET" ) ),
                            tr( "MNU_RESET_VIEW" ), 0, this, false, "Viewers:Reset view");
@@ -1215,9 +1334,9 @@ void OCCViewer_ViewWindow::createActions()
   connect(aAction, SIGNAL(triggered()), this, SLOT(onCloneView()));
   toolMgr()->registerAction( aAction, CloneId );
 
-  aAction = new QtxAction (tr ("MNU_CLIPPING"), aResMgr->loadPixmap ("OCCViewer", tr ("ICON_OCCVIEWER_CLIPPING")),
-                                      tr ("MNU_CLIPPING"), 0, this);
-  aAction->setStatusTip (tr ("DSC_CLIPPING"));
+  aAction = new QtxAction (tr("MNU_CLIPPING"), aResMgr->loadPixmap ("OCCViewer", tr("ICON_OCCVIEWER_CLIPPING")),
+                                      tr("MNU_CLIPPING"), 0, this);
+  aAction->setStatusTip (tr("DSC_CLIPPING"));
   aAction->setCheckable (true);
   connect (aAction, SIGNAL (toggled (bool)), this, SLOT (onClipping (bool)));
   toolMgr()->registerAction (aAction, ClippingId);
@@ -1237,8 +1356,10 @@ void OCCViewer_ViewWindow::createActions()
   if (myModel->trihedronActivated()) {
     aAction = new QtxAction(tr("MNU_SHOW_TRIHEDRE"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_VIEW_TRIHEDRON" ) ),
                              tr( "MNU_SHOW_TRIHEDRE" ), 0, this);
+    aAction->setCheckable( true );
+    aAction->setChecked( true );
     aAction->setStatusTip(tr("DSC_SHOW_TRIHEDRE"));
-    connect(aAction, SIGNAL(triggered()), this, SLOT(onTrihedronShow()));
+    connect(aAction, SIGNAL(toggled(bool)), this, SLOT(onTrihedronShow(bool)));
     toolMgr()->registerAction( aAction, TrihedronShowId );
   }
 
@@ -1265,7 +1386,7 @@ void OCCViewer_ViewWindow::createActions()
   connect(aAction, SIGNAL(toggled(bool)), this, SLOT(onSwitchSelection(bool)));
   toolMgr()->registerAction( aAction, SwitchSelectionId );
 
-  // Graduated axes 
+  // Graduated axes
   aAction = new QtxAction(tr("MNU_GRADUATED_AXES"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_GRADUATED_AXES" ) ),
                            tr( "MNU_GRADUATED_AXES" ), 0, this);
   aAction->setStatusTip(tr("DSC_GRADUATED_AXES"));
@@ -1311,8 +1432,30 @@ void OCCViewer_ViewWindow::createActions()
     toolMgr()->registerAction( aAction, ReturnTo3dViewId );
   }
 
-  // Synchronize View 
+  // Synchronize View
   toolMgr()->registerAction( synchronizeAction(), SynchronizeId );
+#ifdef ENABLE_RAY_TRACING
+  // Ray tracing
+  aAction = new QtxAction( tr("MNU_RAY_TRACING"), aResMgr->loadPixmap( "OCCViewer", tr("ICON_OCCVIEWER_RAY_TRACING") ),
+                           tr("MNU_RAY_TRACING"), 0, this );
+  aAction->setStatusTip( tr("DSC_RAY_TRACING") );
+  connect( aAction, SIGNAL( triggered() ), this, SLOT( onRayTracing() ) );
+  toolMgr()->registerAction( aAction, RayTracingId );
+
+  // Environment texture
+  aAction = new QtxAction( tr("MNU_ENV_TEXTURE"), aResMgr->loadPixmap( "OCCViewer", tr("ICON_OCCVIEWER_ENV_TEXTURE") ),
+                           tr("MNU_ENV_TEXTURE"), 0, this );
+  aAction->setStatusTip( tr("DSC_ENV_TEXTURE") );
+  connect( aAction, SIGNAL( triggered() ), this, SLOT( onEnvTexture() ) );
+  toolMgr()->registerAction( aAction, EnvTextureId );
+
+  // Light source
+  aAction = new QtxAction( tr("MNU_LIGHT_SOURCE"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_LIGHT_SOURCE" ) ),
+                           tr( "MNU_LIGHT_SOURCE" ), 0, this );
+  aAction->setStatusTip( tr("DSC_LIGHT_SOURCE") );
+  connect( aAction, SIGNAL( triggered() ), this, SLOT( onLightSource() ) );
+  toolMgr()->registerAction( aAction, LightSourceId );
+#endif
 }
 
 /*!
@@ -1320,31 +1463,28 @@ void OCCViewer_ViewWindow::createActions()
 */
 void OCCViewer_ViewWindow::createToolBar()
 {
-  QString aToolbarName;
-  switch (my2dMode) {
-  case XYPlane:
-    aToolbarName = tr( "LBL_XYTOOLBAR_LABEL" );
-    break;
-  case XZPlane:
-    aToolbarName = tr( "LBL_XZTOOLBAR_LABEL" );
-    break;
-  case YZPlane:
-    aToolbarName = tr( "LBL_YZTOOLBAR_LABEL" );
-    break;
-  default:
-    aToolbarName = tr( "LBL_3DTOOLBAR_LABEL" );
-  }
-  
-  int tid = toolMgr()->createToolBar( aToolbarName, false );
+  static const char* titles[] = {
+    "LBL_3DTOOLBAR_LABEL",
+    "LBL_XYTOOLBAR_LABEL",
+    "LBL_XZTOOLBAR_LABEL",
+    "LBL_YZTOOLBAR_LABEL",
+  };
+  static const char* names[] = {
+    "OCCViewer3DViewOperations",
+    "OCCViewerXYViewOperations",
+    "OCCViewerXZViewOperations",
+    "OCCViewerYZViewOperations",
+  };
+  int tid = toolMgr()->createToolBar( tr( titles[my2dMode] ),        // title (language-dependant)
+                                     QString( names[my2dMode] ),    // name (language-independant)
+                                     false );                       // disable floatable toolbar
   if ( my2dMode != No2dMode ){
     toolMgr()->append( ReturnTo3dViewId, tid );
     toolMgr()->append( toolMgr()->separator(), tid );
   }
   toolMgr()->append( DumpId, tid );
   toolMgr()->append( SwitchInteractionStyleId, tid );
-#if OCC_VERSION_LARGE > 0x0603000A // available only with OCC-6.3-sp11 and higher version
   toolMgr()->append( SwitchZoomingStyleId, tid );
-#endif
   toolMgr()->append( SwitchPreselectionId, tid );
   toolMgr()->append( SwitchSelectionId, tid );
   if( myModel->trihedronActivated() )
@@ -1353,6 +1493,7 @@ void OCCViewer_ViewWindow::createToolBar()
   QtxMultiAction* aScaleAction = new QtxMultiAction( this );
   aScaleAction->insertAction( toolMgr()->action( FitAllId ) );
   aScaleAction->insertAction( toolMgr()->action( FitRectId ) );
+  aScaleAction->insertAction( toolMgr()->action( FitSelectionId ) );
   aScaleAction->insertAction( toolMgr()->action( ZoomId ) );
   toolMgr()->append( aScaleAction, tid );
 
@@ -1377,6 +1518,10 @@ void OCCViewer_ViewWindow::createToolBar()
     toolMgr()->append( AntiClockWiseId, tid );
     toolMgr()->append( ClockWiseId, tid );
 
+    toolMgr()->append( OrthographicId, tid );
+    toolMgr()->append( PerspectiveId, tid );
+    toolMgr()->append( StereoId, tid );
+
     toolMgr()->append( ResetId, tid );
   }
 
@@ -1387,17 +1532,20 @@ void OCCViewer_ViewWindow::createToolBar()
 
   toolMgr()->append( toolMgr()->separator(), tid );
   toolMgr()->append( CloneId, tid );
-  
+
   toolMgr()->append( toolMgr()->separator(), tid );
   toolMgr()->append( ClippingId, tid );
   toolMgr()->append( AxialScaleId, tid );
-#if OCC_VERSION_LARGE > 0x06030009 // available only with OCC-6.3-sp10 and higher version
   toolMgr()->append( GraduatedAxesId, tid );
-#endif
   toolMgr()->append( AmbientId, tid );
 
   toolMgr()->append( MaximizedId, tid );
   toolMgr()->append( SynchronizeId, tid );
+#ifdef ENABLE_RAY_TRACING
+  toolMgr()->append( RayTracingId, tid );
+  toolMgr()->append( EnvTextureId, tid );
+  toolMgr()->append( LightSourceId, tid );
+#endif
 }
 
 /*!
@@ -1512,10 +1660,159 @@ void OCCViewer_ViewWindow::onResetView()
   myViewPort->getView()->Reset( false );
   myViewPort->fitAll( false, true, false );
   myViewPort->getView()->SetImmediateUpdate( upd );
+  onProjectionType(); // needed to apply projection type properly after reset
   myViewPort->getView()->Update();
   emit vpTransformationFinished( RESETVIEW );
 }
 
+/*!
+  \brief Set the given projection mode.
+
+  Set the given projection mode: Orthographic or Perspective.
+*/
+void OCCViewer_ViewWindow::onProjectionType( QAction* theAction )
+{
+  Handle(V3d_View) aView3d = myViewPort->getView();
+  if ( !aView3d.IsNull() ) {
+    Handle(Graphic3d_Camera) aCamera = aView3d->Camera();
+    if (theAction == toolMgr()->action( OrthographicId )) {
+      myModel->setProjectionType(Orthographic);
+      aCamera->SetProjectionType ( Graphic3d_Camera::Projection_Orthographic );
+      aCamera->SetFOVy(45.0);
+    }
+    else if (theAction == toolMgr()->action( PerspectiveId )) {
+      myModel->setProjectionType(Perspective);
+      aCamera->SetProjectionType ( Graphic3d_Camera::Projection_Perspective );
+      aCamera->SetFOVy(30.0);
+    }
+    if (toolMgr()->action( StereoId )->isChecked()) {
+      aCamera->SetProjectionType ( Graphic3d_Camera::Projection_Stereo );
+      aCamera->SetFOVy(30.0);
+    }
+    aView3d->Redraw();
+    onViewFitAll();
+  }
+}
+
+/*!
+  \brief Sets Stereo projection mode.
+
+  Sets Stereo projection mode.
+*/
+void OCCViewer_ViewWindow::onStereoType( bool activate )
+{
+  Handle(V3d_View) aView3d = myViewPort->getView();
+  if ( !aView3d.IsNull() ) {
+    Handle(Graphic3d_Camera) aCamera = aView3d->Camera();
+    if (activate) {
+      toolMgr()->action( PerspectiveId )->setChecked(true);
+      aCamera->SetProjectionType(Graphic3d_Camera::Projection_Perspective);
+      toolMgr()->action( PerspectiveId )->actionGroup()->setEnabled(false);
+
+      aCamera->SetProjectionType ( Graphic3d_Camera::Projection_Stereo );
+      SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr();
+      setStereoType( aResMgr->integerValue( "OCCViewer", "stereo_type", 0 ) );
+      setAnaglyphFilter( aResMgr->integerValue( "OCCViewer", "anaglyph_filter", 0 ) );
+      setReverseStereo( aResMgr->booleanValue( "OCCViewer", "reverse_stereo", false ) );
+      setVSync( aResMgr->booleanValue( "OCCViewer", "enable_vsync", true ) );
+      setQuadBufferSupport( aResMgr->booleanValue( "OCCViewer", "enable_quad_buffer_support", false ) );
+    }
+    else {
+      toolMgr()->action( PerspectiveId )->actionGroup()->setEnabled(true);
+      if (myModel->projectionType() == Orthographic) {
+        toolMgr()->action( OrthographicId )->setChecked(true);
+        aCamera->SetProjectionType(Graphic3d_Camera::Projection_Orthographic);
+      }
+      else if (myModel->projectionType() == Perspective) {
+        toolMgr()->action( PerspectiveId )->setChecked(true);
+        aCamera->SetProjectionType(Graphic3d_Camera::Projection_Perspective);
+      }
+    }
+    aView3d->Redraw();
+    onViewFitAll();
+  }
+
+  if ( isQuadBufferSupport() && !isOpenGlStereoSupport() && stereoType() == QuadBuffer &&
+       toolMgr()->action( StereoId )->isChecked() )
+    SUIT_MessageBox::warning( 0, tr( "WRN_WARNING" ),  tr( "WRN_SUPPORT_QUAD_BUFFER" ) );
+}
+
+/*!
+  \brief Restore the view.
+
+  Restore the projection mode based on tool-buttons states.
+*/
+void OCCViewer_ViewWindow::onProjectionType()
+{
+  emit vpTransformationStarted( PROJECTION );
+  if (toolMgr()->action( OrthographicId )->isChecked())
+    setProjectionType( Orthographic );
+  if (toolMgr()->action( PerspectiveId )->isChecked())
+    setProjectionType( Perspective );
+  if (toolMgr()->action( StereoId )->isChecked())
+    setProjectionType( Stereo );
+  emit vpTransformationFinished( PROJECTION );
+}
+
+void OCCViewer_ViewWindow::setProjectionType( int mode )
+{
+  QtxAction* anOrthographicAction = dynamic_cast<QtxAction*>( toolMgr()->action( OrthographicId ) );
+  QtxAction* aPerspectiveAction = dynamic_cast<QtxAction*>( toolMgr()->action( PerspectiveId ) );
+  QtxAction* aStereoAction = dynamic_cast<QtxAction*>( toolMgr()->action( StereoId ) );
+  switch ( mode ) {
+    case Orthographic:
+      onProjectionType( anOrthographicAction );
+      break;
+    case Perspective:
+      onProjectionType( aPerspectiveAction );
+      break;
+    case Stereo:
+      onStereoType( true );
+      break;
+  }
+  // update action state if method is called outside
+  if ( mode == Orthographic && !anOrthographicAction->isChecked() ) {
+         anOrthographicAction->setChecked( true );
+         aStereoAction->setChecked( false );
+  }
+  if ( mode == Perspective && !aPerspectiveAction->isChecked() ) {
+         aPerspectiveAction->setChecked( true );
+         aStereoAction->setChecked( false );
+  }
+  if ( mode == Stereo ) {
+    aStereoAction->setChecked( true );
+    if ( anOrthographicAction->isEnabled() ) {
+      anOrthographicAction->setEnabled( false );
+      anOrthographicAction->setChecked( false );
+      aStereoAction->setChecked( false );
+    }
+    else {
+      anOrthographicAction->setEnabled( true );
+      aStereoAction->setChecked( false );
+      anOrthographicAction->setChecked(myModel->projectionType() == Orthographic);
+    }
+    if ( aPerspectiveAction->isEnabled() ) {
+      aPerspectiveAction->setEnabled( false );
+      aPerspectiveAction->setChecked( true );
+      if ( isQuadBufferSupport() && !isOpenGlStereoSupport() && stereoType() == QuadBuffer &&
+           toolMgr()->action( StereoId )->isChecked() )
+        SUIT_MessageBox::warning( 0, tr( "WRN_WARNING" ),  tr( "WRN_SUPPORT_QUAD_BUFFER" ) );
+    }
+    else {
+      aPerspectiveAction->setEnabled( true );
+      aStereoAction->setChecked( false );
+      aPerspectiveAction->setChecked(myModel->projectionType() == Perspective);
+      onProjectionType();
+    }
+  }
+  else {
+    if ( !anOrthographicAction->isEnabled() )
+      anOrthographicAction->setEnabled( true );
+    if ( !aPerspectiveAction->isEnabled() )
+      aPerspectiveAction->setEnabled( true );
+  }
+}
+
 /*!
   \brief Perform "fit all" transformation.
 */
@@ -1526,6 +1823,16 @@ void OCCViewer_ViewWindow::onFitAll()
   emit vpTransformationFinished( FITALLVIEW );
 }
 
+/*!
+  \brief Perform "fit selection" transformation.
+*/
+void OCCViewer_ViewWindow::onFitSelection()
+{
+  emit vpTransformationStarted( FITSELECTION );
+  myModel->getAISContext()->FitSelected( getViewPort()->getView() );
+  emit vpTransformationFinished( FITSELECTION );
+}
+
 /*!
   \brief Called if 'change rotation point' operation is activated.
   \param on action state
@@ -1543,10 +1850,10 @@ void OCCViewer_ViewWindow::onSetRotationPoint( bool on )
     if (!mySetRotationPointDlg->isVisible())
     {
       //if (mySetRotationPointDlg->IsFirstShown())
-      if (myCurrPointType == GRAVITY)
+      if (myCurrPointType == BBCENTER)
       {
         Standard_Real Xcenter, Ycenter, Zcenter;
-        if (computeGravityCenter(Xcenter, Ycenter, Zcenter))
+        if (OCCViewer_Utilities::computeVisibleBBCenter(myViewPort->getView(), Xcenter, Ycenter, Zcenter))
           mySetRotationPointDlg->setCoords(Xcenter, Ycenter, Zcenter);
       }
       mySetRotationPointDlg->show();
@@ -1567,6 +1874,10 @@ void OCCViewer_ViewWindow::onCloneView()
   SUIT_ViewWindow* vw = myManager->createViewWindow();
   //vw->show();
   emit viewCloned( vw );
+  OCCViewer_ViewWindow* occVw = dynamic_cast<OCCViewer_ViewWindow*> (vw);
+  if(occVw && occVw->getView(OCCViewer_ViewFrame::MAIN_VIEW)) {
+    occVw->getView(OCCViewer_ViewFrame::MAIN_VIEW)->synchronize(this);
+  }
 }
 
 /*!
@@ -1575,8 +1886,8 @@ void OCCViewer_ViewWindow::onCloneView()
 void OCCViewer_ViewWindow::onAxialScale()
 {
   if ( !myScalingDlg )
-    myScalingDlg = new OCCViewer_AxialScaleDlg( this );
-  
+    myScalingDlg = new OCCViewer_AxialScaleDlg( this , myModel );
+
   if ( !myScalingDlg->isVisible() )
   {
     myScalingDlg->Update();
@@ -1642,7 +1953,6 @@ void OCCViewer_ViewWindow::performRestoring( const viewAspect& anItem, bool base
 
   Standard_Boolean prev = aView3d->SetImmediateUpdate( Standard_False );
   aView3d->SetScale( anItem.scale );
-  aView3d->SetCenter( anItem.centerX, anItem.centerY );
   aView3d->SetTwist( anItem.twist );
   aView3d->SetAt( anItem.atX, anItem.atY, anItem.atZ );
   aView3d->SetImmediateUpdate( prev );
@@ -1650,12 +1960,33 @@ void OCCViewer_ViewWindow::performRestoring( const viewAspect& anItem, bool base
   aView3d->SetProj( anItem.projX, anItem.projY, anItem.projZ );
   aView3d->SetAxialScale( anItem.scaleX, anItem.scaleY, anItem.scaleZ );
 
+  if ( anItem.centerX != 0.0 || anItem.centerY != 0.0 )
+  {
+    double anUpX = 0.0, anUpY = 0.0, anUpZ = 0.0;
+
+    // "eye" and "at" require conversion to represent center panning
+    // up direction is only available after setting angle of twist and
+    // other view parameters
+    aView3d->Up( anUpX, anUpY, anUpZ );
+
+    gp_Dir aProj( -anItem.projX, -anItem.projY, -anItem.projZ );
+    gp_Dir anUp( anUpX, anUpY, anUpZ );
+    gp_Pnt anAt( anItem.atX, anItem.atY, anItem.atZ );
+    gp_Pnt anEye( anItem.eyeX, anItem.eyeY, anItem.eyeZ );
+    gp_Dir aSide = aProj ^ anUp;
+
+    anAt.Translate( gp_Vec( aSide ) * anItem.centerX );
+    anAt.Translate( gp_Vec( anUp  ) * anItem.centerY );
+
+    aView3d->SetAt( anAt.X(), anAt.Y(), anAt.Z() );
+    aView3d->SetProj( anItem.projX, anItem.projY, anItem.projZ );
+  }
+
   if ( !baseParamsOnly ) {
 
     myModel->setTrihedronShown( anItem.isVisible );
     myModel->setTrihedronSize( anItem.size );
-        
-#if OCC_VERSION_LARGE > 0x06030009 // available only with OCC-6.3-sp10 and higher version
+
     // graduated trihedron
     bool anIsVisible = anItem.gtIsVisible;
     OCCViewer_AxisWidget::AxisData anAxisData[3];
@@ -1701,7 +2032,6 @@ void OCCViewer_ViewWindow::performRestoring( const viewAspect& anItem, bool base
 
     myCubeAxesDlg->SetData( anIsVisible, anAxisData );
     myCubeAxesDlg->ApplyData( aView3d );
-#endif
 
   } // if ( !baseParamsOnly )
 
@@ -1719,9 +2049,9 @@ void OCCViewer_ViewWindow::setRestoreFlag()
 /*!
   \brief Called when action "show/hide trihedron" is activated.
 */
-void OCCViewer_ViewWindow::onTrihedronShow()
+void OCCViewer_ViewWindow::onTrihedronShow(bool show)
 {
-  myModel->toggleTrihedron();
+  myModel->setTrihedronShown(show);
 }
 
 /*!
@@ -1751,7 +2081,7 @@ void OCCViewer_ViewWindow::onSwitchSelection( bool on )
 {
   mySelectionEnabled = on;
   myModel->setSelectionOptions( myModel->isPreselectionEnabled(), isSelectionEnabled() );
-  
+
   // update action state if method is called outside
 
   // preselection
@@ -1776,7 +2106,7 @@ void OCCViewer_ViewWindow::onSwitchInteractionStyle( bool on )
 
   // update action state if method is called outside
   QtxAction* a = dynamic_cast<QtxAction*>( toolMgr()->action( SwitchInteractionStyleId ) );
-  if ( a->isChecked() != on )
+  if ( a && a->isChecked() != on )
     a->setChecked( on );
 }
 
@@ -1789,7 +2119,7 @@ void OCCViewer_ViewWindow::onSwitchZoomingStyle( bool on )
 
   // update action state if method is called outside
   QtxAction* a = dynamic_cast<QtxAction*>( toolMgr()->action( SwitchZoomingStyleId ) );
-  if ( a->isChecked() != on )
+  if ( a && a->isChecked() != on )
     a->setChecked( on );
 }
 
@@ -1833,23 +2163,25 @@ void OCCViewer_ViewWindow::setZoomingStyle( const int theStyle )
   \brief Dump view window contents to the pixmap.
   \return pixmap containing all scene rendered in the window
 */
+//#define USE_OLD_IMPLEMENTATION
 QImage OCCViewer_ViewWindow::dumpView()
 {
   Handle(V3d_View) view = myViewPort->getView();
   if ( view.IsNull() )
     return QImage();
-  
+
   int aWidth = myViewPort->width();
   int aHeight = myViewPort->height();
-  QApplication::syncX();
-  view->Redraw(); // In order to reactivate GL context
-  //view->Update();
 
+#ifdef USE_OLD_IMPLEMENTATION
+  // rnv: Old approach to dump the OCCViewer content via Frame Buffer Object
+
+  view->Redraw();
+
+#ifndef DISABLE_GLVIEWER
   OpenGLUtils_FrameBuffer aFrameBuffer;
-  if( aFrameBuffer.init( aWidth, aHeight ) )
+  if ( aFrameBuffer.init( aWidth, aHeight ) )
   {
-    QImage anImage( aWidth, aHeight, QImage::Format_RGB32 );
-   
     glPushAttrib( GL_VIEWPORT_BIT );
     glViewport( 0, 0, aWidth, aHeight );
     aFrameBuffer.bind();
@@ -1860,6 +2192,8 @@ QImage OCCViewer_ViewWindow::dumpView()
     aFrameBuffer.unbind();
     glPopAttrib();
 
+    QImage anImage( aWidth, aHeight, QImage::Format_RGB32 );
+
     aFrameBuffer.bind();
     glReadPixels( 0, 0, aWidth, aHeight, GL_RGBA, GL_UNSIGNED_BYTE, anImage.bits() );
     aFrameBuffer.unbind();
@@ -1868,37 +2202,77 @@ QImage OCCViewer_ViewWindow::dumpView()
     anImage = anImage.mirrored();
     return anImage;
   }
-  // if frame buffers are unsupported, use old functionality
-  //view->Redraw();
-
-  unsigned char* data = new unsigned char[ aWidth*aHeight*4 ];
 
-  QPoint p = myViewPort->mapFromParent(myViewPort->geometry().topLeft());
+  // if frame buffers are unsupported, use old approach
 
+  unsigned char* data = new unsigned char[ aWidth*aHeight*4 ];
+  QPoint p = myViewPort->mapFromParent( myViewPort->geometry().topLeft() );
   glReadPixels( p.x(), p.y(), aWidth, aHeight, GL_RGBA, GL_UNSIGNED_BYTE,
                 data);
-
   QImage anImage( data, aWidth, aHeight, QImage::Format_ARGB32 );
   anImage = anImage.mirrored();
   anImage = anImage.rgbSwapped();
   return anImage;
+
+#else // DISABLE_GLVIEWER
+
+  return QImage();
+
+#endif // DISABLE_GLVIEWER
+
+#else // USE_OLD_IMPLEMENTATION
+  // rnv: New approach is to use OCCT built-in procedure
+
+  Image_PixMap aPix;
+  view->ToPixMap(aPix, aWidth, aHeight, Graphic3d_BT_RGB);
+  
+  QImage anImage( aWidth, aHeight, QImage::Format_ARGB32 );
+  for ( int i = 0; i < aWidth; i++ ) {
+    for ( int j = 0; j < aHeight; j++ ) {
+      Quantity_Color pixel = aPix.PixelColor( i, j ).GetRGB();
+      QColor color = QColor::fromRgbF( pixel.Red(), pixel.Green(), pixel.Blue() );
+      anImage.setPixelColor( i, j, color );
+    }
+  }
+    
+  if ( aPix.IsTopDown() )
+    anImage = anImage.mirrored();
+  return anImage;
+
+#endif // USE_OLD_IMPLEMENTATION
 }
 
-bool OCCViewer_ViewWindow::dumpViewToFormat( const QImage& img, 
-                                             const QString& fileName, 
+bool OCCViewer_ViewWindow::dumpViewToFormat( const QImage& img,
+                                             const QString& fileName,
                                              const QString& format )
 {
-  if ( format != "PS" && format != "EPS")
-    return SUIT_ViewWindow::dumpViewToFormat( img, fileName, format );
+  bool res = false;
+  QApplication::setOverrideCursor( Qt::WaitCursor );
 
-  Handle(Visual3d_View) a3dView = myViewPort->getView()->View();
+  Handle(Graphic3d_CView) a3dView = myViewPort->getView()->View();
 
-  if (format == "PS")
-    a3dView->Export(strdup(qPrintable(fileName)), Graphic3d_EF_PostScript);
-  else if (format == "EPS")
-    a3dView->Export(strdup(qPrintable(fileName)), Graphic3d_EF_EnhPostScript);
+  if (format == "PS") {
+    Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast(myViewPort->getViewer()->Driver());
+    OpenGl_Caps* aCaps = &aDriver->ChangeOptions();
+    int prev = aCaps->ffpEnable;
+    aCaps->ffpEnable = 1;
+    res = a3dView->Export(strdup(qUtf8Printable(fileName)), Graphic3d_EF_PostScript);
+    aCaps->ffpEnable = prev;
+  }
+  else if (format == "EPS") {
+    Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast(myViewPort->getViewer()->Driver());
+    OpenGl_Caps* aCaps = &aDriver->ChangeOptions();
+    int prev = aCaps->ffpEnable;
+    aCaps->ffpEnable = 1;
+    res = a3dView->Export(strdup(qUtf8Printable(fileName)), Graphic3d_EF_EnhPostScript);
+    aCaps->ffpEnable = prev;
+  }
+  else {
+    res = myViewPort->getView()->Dump( fileName.toStdString().c_str() );
+  }
 
-  return true;
+  QApplication::restoreOverrideCursor();
+  return res;
 }
 
 
@@ -1935,23 +2309,19 @@ void OCCViewer_ViewWindow::setCuttingPlane( bool on, const double x,  const doub
     gp_Pln pln (gp_Pnt(x, y, z), gp_Dir(dx, dy, dz));
     double a, b, c, d;
     pln.Coefficients(a, b, c, d);
-    
-    Graphic3d_SequenceOfHClipPlane aPlanes = view->GetClipPlanes();
-    Handle(Graphic3d_ClipPlane) aClipPlane;
-    if(aPlanes.Size() > 0 ) {
-      Graphic3d_SequenceOfHClipPlane::Iterator anIter (aPlanes);
-      aClipPlane = anIter.Value();
+    Handle(Graphic3d_SequenceOfHClipPlane) aPlanes = view->ClipPlanes();
+    Graphic3d_SequenceOfHClipPlane::Iterator anIter (*aPlanes);
+    if(aPlanes->Size() > 0 ) {
+      Handle(Graphic3d_ClipPlane) aClipPlane = anIter.Value();
       aClipPlane->SetEquation(pln);
       aClipPlane->SetOn(Standard_True);
     } else {
-      aClipPlane = new Graphic3d_ClipPlane(pln);
-      view->AddClipPlane(aClipPlane);
-      aClipPlane->SetOn(Standard_True);
+      view->AddClipPlane( myModel->createClipPlane( pln, Standard_True ) );
     }
   }
   else {
-    Graphic3d_SequenceOfHClipPlane aPlanes = view->GetClipPlanes();
-    Graphic3d_SequenceOfHClipPlane::Iterator anIter (aPlanes);
+    Handle(Graphic3d_SequenceOfHClipPlane) aPlanes = view->ClipPlanes();
+    Graphic3d_SequenceOfHClipPlane::Iterator anIter (*aPlanes);
     for( ;anIter.More();anIter.Next() ){
       Handle(Graphic3d_ClipPlane) aClipPlane = anIter.Value();
       aClipPlane->SetOn(Standard_False);
@@ -1978,8 +2348,8 @@ bool OCCViewer_ViewWindow::isCuttingPlane()
 {
   Handle(V3d_View) view = myViewPort->getView();
   bool res = false;
-  Graphic3d_SequenceOfHClipPlane aPlanes = view->GetClipPlanes();
-  Graphic3d_SequenceOfHClipPlane::Iterator anIter (aPlanes);
+  Handle(Graphic3d_SequenceOfHClipPlane) aPlanes = view->ClipPlanes();
+  Graphic3d_SequenceOfHClipPlane::Iterator anIter (*aPlanes);
   for( ;anIter.More();anIter.Next() ) {
     Handle(Graphic3d_ClipPlane) aClipPlane = anIter.Value();
     if(aClipPlane->IsOn()) {
@@ -1996,13 +2366,12 @@ bool OCCViewer_ViewWindow::isCuttingPlane()
 */
 viewAspect OCCViewer_ViewWindow::getViewParams() const
 {
-  double centerX, centerY, projX, projY, projZ, twist;
+  double projX, projY, projZ, twist;
   double atX, atY, atZ, eyeX, eyeY, eyeZ;
   double aScaleX, aScaleY, aScaleZ;
 
   Handle(V3d_View) aView3d = myViewPort->getView();
 
-  aView3d->Center( centerX, centerY );
   aView3d->Proj( projX, projY, projZ );
   aView3d->At( atX, atY, atZ );
   aView3d->Eye( eyeX, eyeY, eyeZ );
@@ -2017,8 +2386,6 @@ viewAspect OCCViewer_ViewWindow::getViewParams() const
 
   viewAspect params;
   params.scale    = aView3d->Scale();
-  params.centerX  = centerX;
-  params.centerY  = centerY;
   params.projX    = projX;
   params.projY    = projY;
   params.projZ    = projZ;
@@ -2036,7 +2403,6 @@ viewAspect OCCViewer_ViewWindow::getViewParams() const
   params.isVisible= isShown;
   params.size     = size;
 
-#if OCC_VERSION_LARGE > 0x06030009 // available only with OCC-6.3-sp10 and higher version
   // graduated trihedron
   bool anIsVisible = false;
   OCCViewer_AxisWidget::AxisData anAxisData[3];
@@ -2082,7 +2448,6 @@ viewAspect OCCViewer_ViewWindow::getViewParams() const
   params.gtTickmarkLengthX = anAxisData[0].TickmarkLength;
   params.gtTickmarkLengthY = anAxisData[1].TickmarkLength;
   params.gtTickmarkLengthZ = anAxisData[2].TickmarkLength;
-#endif
 
   return params;
 }
@@ -2098,8 +2463,6 @@ QString OCCViewer_ViewWindow::getVisualParameters()
   QStringList data;
 
   data << QString( "scale=%1" )    .arg( params.scale,   0, 'e', 12 );
-  data << QString( "centerX=%1" )  .arg( params.centerX, 0, 'e', 12 );
-  data << QString( "centerY=%1" )  .arg( params.centerY, 0, 'e', 12 );
   data << QString( "projX=%1" )    .arg( params.projX,   0, 'e', 12 );
   data << QString( "projY=%1" )    .arg( params.projY,   0, 'e', 12 );
   data << QString( "projZ=%1" )    .arg( params.projZ,   0, 'e', 12 );
@@ -2117,28 +2480,46 @@ QString OCCViewer_ViewWindow::getVisualParameters()
   data << QString( "size=%1" )     .arg( params.size,    0, 'f',  2 );
 
   ClipPlanesList aPlanes =  myModel->getClipPlanes();
-  for ( int i=0; i < aPlanes.size(); i++ ) {
+  for ( int i=0; i < aPlanes.size(); i++ )
+  {
     OCCViewer_ClipPlane& aPlane = aPlanes[i];
     QString ClippingPlane = QString( "ClippingPlane%1=").arg( i+1 );
-    ClippingPlane +=  QString( "Mode~%1;").arg( (int)aPlane.PlaneMode );
+    ClippingPlane +=  QString( "Mode~%1;").arg( (int)aPlane.Mode );
     ClippingPlane +=  QString( "IsActive~%1;").arg( aPlane.IsOn );
-    ClippingPlane += QString( "AbsoluteOrientation~%1;" ).arg( aPlane.Orientation );
-    ClippingPlane += QString( "IsInvert~%1;" ).arg( aPlane.IsInvert );
+    switch ( aPlane.Mode )
+    {
+      case OCCViewer_ClipPlane::Absolute :
+      {
+        ClippingPlane += QString( "AbsoluteOrientation~%1;" ).arg( aPlane.OrientationType );
+
+        if ( aPlane.OrientationType == OCCViewer_ClipPlane::AbsoluteCustom )
+        {
+          ClippingPlane += QString( "Dx~%1;" ).arg( aPlane.AbsoluteOrientation.Dx );
+          ClippingPlane += QString( "Dy~%1;" ).arg( aPlane.AbsoluteOrientation.Dy );
+          ClippingPlane += QString( "Dz~%1;" ).arg( aPlane.AbsoluteOrientation.Dz );
+        }
+        else
+        {
+          ClippingPlane += QString( "IsInvert~%1;" ).arg( aPlane.AbsoluteOrientation.IsInvert );
+        }
+      }
+      break;
+
+      case OCCViewer_ClipPlane::Relative :
+      {
+        ClippingPlane += QString( "RelativeOrientation~%1;" ).arg( aPlane.OrientationType );
+        ClippingPlane += QString( "Rotation1~%1;" ).arg( aPlane.RelativeOrientation.Rotation1 );
+        ClippingPlane += QString( "Rotation2~%1" ).arg( aPlane.RelativeOrientation.Rotation2 );
+      }
+      break;
+    }
+
     ClippingPlane +=  QString( "X~%1;" ).arg( aPlane.X );
     ClippingPlane +=  QString( "Y~%1;" ).arg( aPlane.Y );
     ClippingPlane +=  QString( "Z~%1;" ).arg( aPlane.Z );
-    ClippingPlane +=  QString( "Dx~%1;" ).arg( aPlane.Dx );
-    ClippingPlane +=  QString( "Dy~%1;" ).arg( aPlane.Dy );;
-    ClippingPlane +=  QString( "Dz~%1;" ).arg( aPlane.Dz );
-    ClippingPlane +=  QString( "RelativeOrientation~%1;" ).arg( aPlane.RelativeMode.Orientation );
-    ClippingPlane +=  QString( "Distance~%1;" ).arg( aPlane.RelativeMode.Distance );
-    ClippingPlane +=  QString( "Rotation1~%1;" ).arg( aPlane.RelativeMode.Rotation1 );
-    ClippingPlane +=  QString( "Rotation2~%1" ).arg( aPlane.RelativeMode.Rotation2 );
     data << ClippingPlane;
   }
 
-
-#if OCC_VERSION_LARGE > 0x06030009 // available only with OCC-6.3-sp10 or newer version
   // graduated trihedron
   data << QString( "gtIsVisible=%1" )      .arg( params.gtIsVisible );
   data << QString( "gtDrawNameX=%1" )      .arg( params.gtDrawNameX );
@@ -2180,7 +2561,58 @@ QString OCCViewer_ViewWindow::getVisualParameters()
   data << QString( "gtTickmarkLengthX=%1" ).arg( params.gtTickmarkLengthX );
   data << QString( "gtTickmarkLengthY=%1" ).arg( params.gtTickmarkLengthY );
   data << QString( "gtTickmarkLengthZ=%1" ).arg( params.gtTickmarkLengthZ );
-#endif
+
+  // ray tracing parameters
+  Graphic3d_RenderingParams rendParams = this->getViewPort()->getView()->RenderingParams();
+  if ( rendParams.Method == Graphic3d_RM_RAYTRACING ) {
+    QString RayTracing = "rayTracing=";
+    RayTracing += QString( "rtDepth~%1;" ).arg( rendParams.RaytracingDepth );
+    RayTracing += QString( "rtReflection~%1;" ).arg( rendParams.IsReflectionEnabled );
+    RayTracing += QString( "rtAntialiasing~%1;" ).arg( rendParams.IsAntialiasingEnabled );
+    RayTracing += QString( "rtShadow~%1;" ).arg( rendParams.IsShadowEnabled );
+    RayTracing += QString( "rtTransShadow~%1;" ).arg( rendParams.IsTransparentShadowEnabled );
+    data << RayTracing;
+  }
+
+  // environment texture parameters
+  Handle(Graphic3d_TextureEnv) aTexture = this->getViewPort()->getView()->TextureEnv();
+  if ( !aTexture.IsNull() ) {
+    QString EnvTexture = "envTexture=";
+    if ( aTexture->Name() == Graphic3d_NOT_ENV_UNKNOWN ) {
+      TCollection_AsciiString aFileName;
+      aTexture->Path().SystemName( aFileName );
+      EnvTexture += QString( "etFile~%1;" ).arg( aFileName.ToCString() );
+    }
+    else
+      EnvTexture += QString( "etNumber~%1;" ).arg( aTexture->Name() );
+    data << EnvTexture;
+  }
+
+  // light source parameters
+  myModel->getViewer3d()->InitDefinedLights();
+  while ( myModel->getViewer3d()->MoreDefinedLights() )
+  {
+    Handle(V3d_Light) aLight = myModel->getViewer3d()->DefinedLight();
+    if ( aLight->Type() != V3d_AMBIENT ) {
+      QString LightSource = QString( "lightSource=" );
+      LightSource += QString( "lightType~%1;" ).arg( aLight->Type() );
+      double aX, aY, aZ;
+      if ( aLight->Type() == V3d_DIRECTIONAL )
+        Handle(V3d_DirectionalLight)::DownCast( aLight )->Direction( aX, aY, aZ );
+      else if ( aLight->Type() == V3d_POSITIONAL )
+        Handle(V3d_PositionalLight)::DownCast( aLight )->Position( aX, aY, aZ );
+      LightSource += QString( "lightX~%1;" ).arg( aX );
+      LightSource += QString( "lightY~%1;" ).arg( aY );
+      LightSource += QString( "lightZ~%1;" ).arg( aZ );
+      LightSource += QString( "lightColorR~%1;" ).arg( aLight->Color().Red() );
+      LightSource += QString( "lightColorG~%1;" ).arg( aLight->Color().Green() );
+      LightSource += QString( "lightColorB~%1;" ).arg( aLight->Color().Blue() );
+      LightSource += QString( "lightHeadlight~%1;" ).arg( aLight->Headlight() );
+      data << LightSource;
+    }
+    myModel->getViewer3d()->NextDefinedLights();
+  }
+
   QString bg = Qtx::backgroundToString( background() ).replace( "=", "$" );
   data << QString( "background=%1" ).arg( bg );
 
@@ -2220,28 +2652,43 @@ void OCCViewer_ViewWindow::setVisualParameters( const QString& parameters )
       else if ( paramName == "scaleZ" )            params.scaleZ            = paramValue.toDouble();
       else if ( paramName == "isVisible" )         params.isVisible         = paramValue.toInt();
       else if ( paramName == "size" )              params.size              = paramValue.toDouble();
-      else if ( paramName.contains( "ClippingPlane" ) ) {
+      else if ( paramName.contains( "ClippingPlane" ) )
+      {
         QStringList ClipPlaneData = paramValue.split( ';' );
         OCCViewer_ClipPlane aPlane;
-        foreach( QString ClipPlaneParam, ClipPlaneData ) {
-         QString ClipPlane_paramName  = ClipPlaneParam.section( '~', 0, 0 ).trimmed();
-         QString ClipPlane_paramValue = ClipPlaneParam.section( '~', 1, 1 ).trimmed();
-            if      ( ClipPlane_paramName == "Mode" )                aPlane.PlaneMode                  = ( ClipPlaneMode )ClipPlane_paramValue.toInt();
-            else if ( ClipPlane_paramName == "IsActive" )            aPlane.IsOn                       = ClipPlane_paramValue.toInt();
-            else if ( ClipPlane_paramName == "AbsoluteOrientation" ) aPlane.Orientation                = ClipPlane_paramValue.toInt();
-            else if ( ClipPlane_paramName == "IsInvert" )            aPlane.IsInvert                   = ClipPlane_paramValue.toInt();
-            else if ( ClipPlane_paramName == "X" )                   aPlane.X                          = ClipPlane_paramValue.toDouble();
-            else if ( ClipPlane_paramName == "Y" )                   aPlane.Y                          = ClipPlane_paramValue.toDouble();
-            else if ( ClipPlane_paramName == "Z" )                   aPlane.Z                          = ClipPlane_paramValue.toDouble();
-            else if ( ClipPlane_paramName == "Dx" )                  aPlane.Dx                         = ClipPlane_paramValue.toDouble();
-            else if ( ClipPlane_paramName == "Dy" )                  aPlane.Dy                         = ClipPlane_paramValue.toDouble();
-            else if ( ClipPlane_paramName == "Dz" )                  aPlane.Dz                         = ClipPlane_paramValue.toDouble();
-            else if ( ClipPlane_paramName == "RelativeOrientation" ) aPlane.RelativeMode.Orientation   = ClipPlane_paramValue.toInt();
-            else if ( ClipPlane_paramName == "Distance" )            aPlane.RelativeMode.Distance      = ClipPlane_paramValue.toDouble();
-            else if ( ClipPlane_paramName == "Rotation1" )           aPlane.RelativeMode.Rotation1     = ClipPlane_paramValue.toDouble();
-            else if ( ClipPlane_paramName == "Rotation2" )           aPlane.RelativeMode.Rotation2     = ClipPlane_paramValue.toDouble();
+        foreach( QString ClipPlaneParam, ClipPlaneData )
+        {
+          QString ClipPlane_paramName  = ClipPlaneParam.section( '~', 0, 0 ).trimmed();
+          QString ClipPlane_paramValue = ClipPlaneParam.section( '~', 1, 1 ).trimmed();
+          if ( ClipPlane_paramName == "Mode" )
+          {
+            aPlane.Mode = ( OCCViewer_ClipPlane::PlaneMode ) ClipPlane_paramValue.toInt();
+          }
+          else if ( ClipPlane_paramName == "IsActive" ) aPlane.IsOn = ClipPlane_paramValue.toInt();
+          else if ( ClipPlane_paramName == "X" )        aPlane.X    = ClipPlane_paramValue.toDouble();
+          else if ( ClipPlane_paramName == "Y" )        aPlane.Y    = ClipPlane_paramValue.toDouble();
+          else if ( ClipPlane_paramName == "Z" )        aPlane.Z    = ClipPlane_paramValue.toDouble();
+          else
+          {
+            switch ( aPlane.Mode )
+            {
+              case OCCViewer_ClipPlane::Absolute :
+                if      ( ClipPlane_paramName == "Dx" ) aPlane.AbsoluteOrientation.Dx = ClipPlane_paramValue.toDouble();
+                else if ( ClipPlane_paramName == "Dy" ) aPlane.AbsoluteOrientation.Dy = ClipPlane_paramValue.toDouble();
+                else if ( ClipPlane_paramName == "Dz" ) aPlane.AbsoluteOrientation.Dz = ClipPlane_paramValue.toDouble();
+                else if ( ClipPlane_paramName == "IsInvert" ) aPlane.AbsoluteOrientation.IsInvert = ClipPlane_paramValue.toInt();
+                else if ( ClipPlane_paramName == "AbsoluteOrientation" ) aPlane.OrientationType = ClipPlane_paramValue.toInt();
+                break;
+
+              case OCCViewer_ClipPlane::Relative :
+                if      ( ClipPlane_paramName == "RelativeOrientation" ) aPlane.OrientationType = ClipPlane_paramValue.toInt();
+                else if ( ClipPlane_paramName == "Rotation1" )           aPlane.RelativeOrientation.Rotation1 = ClipPlane_paramValue.toDouble();
+                else if ( ClipPlane_paramName == "Rotation2" )           aPlane.RelativeOrientation.Rotation2 = ClipPlane_paramValue.toDouble();
+                break;
+            }
+          }
         }
-       aClipPlanes.push_back(aPlane);
+        aClipPlanes.push_back(aPlane);
       }
       // graduated trihedron
       else if ( paramName == "gtIsVisible" )       params.gtIsVisible       = paramValue.toInt();
@@ -2284,6 +2731,83 @@ void OCCViewer_ViewWindow::setVisualParameters( const QString& parameters )
       else if ( paramName == "gtTickmarkLengthX" ) params.gtTickmarkLengthX = paramValue.toInt();
       else if ( paramName == "gtTickmarkLengthY" ) params.gtTickmarkLengthY = paramValue.toInt();
       else if ( paramName == "gtTickmarkLengthZ" ) params.gtTickmarkLengthZ = paramValue.toInt();
+      else if ( paramName == "rayTracing" )
+      {
+        Graphic3d_RenderingParams& rendParams = this->getViewPort()->getView()->ChangeRenderingParams();
+        rendParams.Method = Graphic3d_RM_RAYTRACING;
+        QStringList rtData = paramValue.split( ';' );
+        foreach( QString rtParam, rtData )
+        {
+          QString rt_paramName  = rtParam.section( '~', 0, 0 ).trimmed();
+          QString rt_paramValue = rtParam.section( '~', 1, 1 ).trimmed();
+          if ( rt_paramName == "rtDepth" ) rendParams.RaytracingDepth = rt_paramValue.toInt();
+          else if ( rt_paramName == "rtReflection" ) rendParams.IsReflectionEnabled = rt_paramValue.toInt();
+          else if ( rt_paramName == "rtAntialiasing" ) rendParams.IsAntialiasingEnabled = rt_paramValue.toInt();
+          else if ( rt_paramName == "rtShadow" ) rendParams.IsShadowEnabled = rt_paramValue.toInt();
+          else if ( rt_paramName == "rtTransShadow" ) rendParams.IsTransparentShadowEnabled = rt_paramValue.toInt();
+        }
+      }
+      else if ( paramName == "envTexture" )
+      {
+        Handle(Graphic3d_TextureEnv) aTexture;
+        QStringList etData = paramValue.split( ';' );
+        foreach( QString etParam, etData )
+        {
+          QString et_paramName  = etParam.section( '~', 0, 0 ).trimmed();
+          QString et_paramValue = etParam.section( '~', 1, 1 ).trimmed();
+          if ( et_paramName == "etNumber" )
+            aTexture = new Graphic3d_TextureEnv( Graphic3d_NameOfTextureEnv( et_paramValue.toInt() ) );
+          else if ( et_paramName == "etFile" )
+            aTexture = new Graphic3d_TextureEnv( TCollection_AsciiString( et_paramValue.toStdString().c_str() ) );
+          Handle(V3d_View) aView = this->getViewPort()->getView();
+          aView->SetTextureEnv( aTexture );
+        }
+      }
+      else if ( paramName == "lightSource" )
+      {
+        myModel->getViewer3d()->InitDefinedLights();
+        while ( myModel->getViewer3d()->MoreDefinedLights() )
+        {
+          Handle(V3d_Light) aLight = myModel->getViewer3d()->DefinedLight();
+          if( aLight->Type() != V3d_AMBIENT ) {
+            myModel->getViewer3d()->DelLight( aLight );
+           myModel->getViewer3d()->InitDefinedLights();
+         } else {
+           myModel->getViewer3d()->NextDefinedLights();
+         }
+        }
+        double aX, aY, aZ;
+        double cR, cG, cB;
+        V3d_TypeOfLight aType;
+        bool isHeadlight;
+        QStringList lsData = paramValue.split( ';' );
+        foreach( QString lsParam, lsData )
+        {
+          QString ls_paramName  = lsParam.section( '~', 0, 0 ).trimmed();
+          QString ls_paramValue = lsParam.section( '~', 1, 1 ).trimmed();
+          if ( ls_paramName == "lightType" ) aType = V3d_TypeOfLight( ls_paramValue.toInt() );
+          else if ( ls_paramName == "lightX" ) aX = ls_paramValue.toDouble();
+          else if ( ls_paramName == "lightY" ) aY = ls_paramValue.toDouble();
+          else if ( ls_paramName == "lightZ" ) aZ = ls_paramValue.toDouble();
+          else if ( ls_paramName == "lightColorR" ) cR = ls_paramValue.toDouble();
+          else if ( ls_paramName == "lightColorG" ) cG = ls_paramValue.toDouble();
+          else if ( ls_paramName == "lightColorB" ) cB = ls_paramValue.toDouble();
+          else if ( ls_paramName == "lightHeadlight" ) isHeadlight = ls_paramValue.toInt();
+        }
+        Quantity_Color aColor = Quantity_Color( cR, cG, cB, Quantity_TOC_RGB );
+        if( aType == V3d_DIRECTIONAL ) {
+          Handle(V3d_DirectionalLight) aLight = new V3d_DirectionalLight( myModel->getViewer3d() );
+          aLight->SetDirection( aX, aY, aZ );
+          aLight->SetColor( aColor );
+          aLight->SetHeadlight( isHeadlight );
+          myModel->getViewer3d()->SetLightOn( aLight );
+        }
+        else if( aType == V3d_POSITIONAL ) {
+          Handle(V3d_PositionalLight) aLight = new V3d_PositionalLight( myModel->getViewer3d(), aX, aY, aZ, aColor.Name() );
+          aLight->SetHeadlight( isHeadlight );
+          myModel->getViewer3d()->SetLightOn( aLight );
+        }
+      }
       else if ( paramName == "background" )        {
   QString bg = paramValue.replace( "$", "=" );
   bgData = Qtx::stringToBackground( bg );
@@ -2312,7 +2836,7 @@ void OCCViewer_ViewWindow::setVisualParameters( const QString& parameters )
     params.isVisible = data.count() > idx ? data[idx++].toInt()    : 1;
     params.size      = data.count() > idx ? data[idx++].toDouble() : 100.0;
   }
-  performRestoring( params );  
+  performRestoring( params );
   setBackground( bgData );
   myModel->setClipPlanes(aClipPlanes);
 }
@@ -2342,6 +2866,18 @@ void OCCViewer_ViewWindow::hideEvent( QHideEvent* theEvent )
 }
 
 
+/*!
+    Save old cursor. [ protected ]
+*/
+void OCCViewer_ViewWindow::saveCursor()
+{
+  QCursor* aCursor = NULL;
+  if ( myViewPort )
+    aCursor = myViewPort->getDefaultCursor();
+  myCursor = ( aCursor ? *aCursor : cursor() );
+}
+
+
 /*!
     Creates default sketcher. [ virtual protected ]
 */
@@ -2544,8 +3080,8 @@ void OCCViewer_ViewWindow::setMaximized(bool toMaximize, bool toSendSignal)
   QAction* anAction2 =  toolMgr()->action( ReturnTo3dViewId );
   SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr();
   if ( toMaximize ) {
-    anAction->setText( tr( "MNU_MINIMIZE_VIEW" ) );  
-    anAction->setToolTip( tr( "MNU_MINIMIZE_VIEW" ) );  
+    anAction->setText( tr( "MNU_MINIMIZE_VIEW" ) );
+    anAction->setToolTip( tr( "MNU_MINIMIZE_VIEW" ) );
     anAction->setIcon( aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_MINIMIZE" ) ) );
     anAction->setStatusTip( tr( "DSC_MINIMIZE_VIEW" ) );
     if ( anAction2 && my2dMode != No2dMode ) toolMgr()->show( ReturnTo3dViewId );
@@ -2554,8 +3090,8 @@ void OCCViewer_ViewWindow::setMaximized(bool toMaximize, bool toSendSignal)
     }
   }
   else {
-    anAction->setText( tr( "MNU_MAXIMIZE_VIEW" ) );  
-    anAction->setToolTip( tr( "MNU_MAXIMIZE_VIEW" ) );  
+    anAction->setText( tr( "MNU_MAXIMIZE_VIEW" ) );
+    anAction->setToolTip( tr( "MNU_MAXIMIZE_VIEW" ) );
     anAction->setIcon( aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_MAXIMIZE" ) ) );
     anAction->setStatusTip( tr( "DSC_MAXIMIZE_VIEW" ) );
     if ( anAction2 && my2dMode != No2dMode ) toolMgr()->hide( ReturnTo3dViewId );
@@ -2571,13 +3107,13 @@ bool OCCViewer_ViewWindow::isMaximized() const
 }
 
 void OCCViewer_ViewWindow::setSketcherStyle( bool enable )
-{ 
-  IsSketcherStyle = enable; 
+{
+  IsSketcherStyle = enable;
 }
 
-bool OCCViewer_ViewWindow::isSketcherStyle() const 
-{ 
-  return IsSketcherStyle; 
+bool OCCViewer_ViewWindow::isSketcherStyle() const
+{
+  return IsSketcherStyle;
 }
 
 
@@ -2586,12 +3122,214 @@ void OCCViewer_ViewWindow::set2dMode(Mode2dType theType)
   my2dMode = theType;
 }
 
-// obsolete   
+int OCCViewer_ViewWindow::projectionType() const
+{
+  int mode = Orthographic;
+  Handle(V3d_View) aView3d = myViewPort->getView();
+  if ( !aView3d.IsNull() ) {
+    Handle(Graphic3d_Camera) aCamera = aView3d->Camera();
+    if (aCamera->ProjectionType() == Graphic3d_Camera::Projection_Perspective)
+      mode = Perspective;
+    if (aCamera->ProjectionType() == Graphic3d_Camera::Projection_Orthographic)
+      mode = Orthographic;
+    if (aCamera->ProjectionType() == Graphic3d_Camera::Projection_Stereo)
+      mode = Stereo;
+  }
+  return mode;
+}
+
+void OCCViewer_ViewWindow::setStereoType( int type )
+{
+  Handle(V3d_View) aView3d = myViewPort->getView();
+  if ( !aView3d.IsNull() ) {
+    Graphic3d_RenderingParams* aParams = &aView3d->ChangeRenderingParams();
+    aParams->StereoMode = (Graphic3d_StereoMode)type;
+  }
+}
+
+int OCCViewer_ViewWindow::stereoType() const
+{
+  int type = QuadBuffer;
+  Handle(V3d_View) aView3d = myViewPort->getView();
+  if ( !aView3d.IsNull() ) {
+    Graphic3d_RenderingParams* aParams = &aView3d->ChangeRenderingParams();
+    type = (OCCViewer_ViewWindow::StereoType)aParams->StereoMode;
+  }
+  return type;
+}
+
+void OCCViewer_ViewWindow::setAnaglyphFilter( int type )
+{
+  Handle(V3d_View) aView3d = myViewPort->getView();
+  if ( !aView3d.IsNull() ) {
+    Graphic3d_RenderingParams* aParams = &aView3d->ChangeRenderingParams();
+    if (type == RedCyan)
+      aParams->AnaglyphFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized;
+    if (type == YellowBlue)
+      aParams->AnaglyphFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized;
+    if (type == GreenMagenta)
+      aParams->AnaglyphFilter = Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple;
+  }
+}
+
+int OCCViewer_ViewWindow::anaglyphFilter() const
+{
+  int type = RedCyan;
+  Handle(V3d_View) aView3d = myViewPort->getView();
+  if ( !aView3d.IsNull() ) {
+    Graphic3d_RenderingParams* aParams = &aView3d->ChangeRenderingParams();
+    if (aParams->AnaglyphFilter == Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized)
+      type = RedCyan;
+    if (aParams->AnaglyphFilter == Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized)
+      type = YellowBlue;
+    if (aParams->AnaglyphFilter == Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple)
+      type = GreenMagenta;
+  }
+  return type;
+}
+
+void OCCViewer_ViewWindow::setStereographicFocus( int type, double value )
+{
+  Handle(V3d_View) aView3d = myViewPort->getView();
+  if ( !aView3d.IsNull() ) {
+    Handle(Graphic3d_Camera) aCamera = aView3d->Camera();
+    aCamera->SetZFocus( (Graphic3d_Camera::FocusType) type, value );
+  }
+}
+
+int OCCViewer_ViewWindow::stereographicFocusType() const
+{
+  int type = Relative;
+  Handle(V3d_View) aView3d = myViewPort->getView();
+  if ( !aView3d.IsNull() ) {
+    Handle(Graphic3d_Camera) aCamera = aView3d->Camera();
+    type = (OCCViewer_ViewWindow::FocusIODType)aCamera->ZFocusType();
+  }
+  return type;
+}
+
+double OCCViewer_ViewWindow::stereographicFocusValue() const
+{
+  double value = 1.0;
+  Handle(V3d_View) aView3d = myViewPort->getView();
+  if ( !aView3d.IsNull() ) {
+    Handle(Graphic3d_Camera) aCamera = aView3d->Camera();
+    value = aCamera->ZFocus();
+  }
+  return value;
+}
+
+void OCCViewer_ViewWindow::setInterocularDistance( int type, double value )
+{
+  Handle(V3d_View) aView3d = myViewPort->getView();
+  if ( !aView3d.IsNull() ) {
+    Handle(Graphic3d_Camera) aCamera = aView3d->Camera();
+    aCamera->SetIOD( (Graphic3d_Camera::IODType) type, value );
+  }
+}
+
+int OCCViewer_ViewWindow::interocularDistanceType() const
+{
+  int type = Relative;
+  Handle(V3d_View) aView3d = myViewPort->getView();
+  if ( !aView3d.IsNull() ) {
+    Handle(Graphic3d_Camera) aCamera = aView3d->Camera();
+    type = (OCCViewer_ViewWindow::FocusIODType)aCamera->GetIODType();
+  }
+  return type;
+}
+
+double OCCViewer_ViewWindow::interocularDistanceValue() const
+{
+  double value = 0.05;
+  Handle(V3d_View) aView3d = myViewPort->getView();
+  if ( !aView3d.IsNull() ) {
+    Handle(Graphic3d_Camera) aCamera = aView3d->Camera();
+    value = aCamera->IOD();
+  }
+  return value;
+}
+
+void OCCViewer_ViewWindow::setReverseStereo( bool reverse )
+{
+  Handle(V3d_View) aView3d = myViewPort->getView();
+  if ( !aView3d.IsNull() ) {
+    Graphic3d_RenderingParams* aParams = &aView3d->ChangeRenderingParams();
+    aParams->ToReverseStereo = reverse;
+  }
+}
+
+bool OCCViewer_ViewWindow::isReverseStereo() const
+{
+  int reverse = false;
+  Handle(V3d_View) aView3d = myViewPort->getView();
+  if ( !aView3d.IsNull() ) {
+    Graphic3d_RenderingParams* aParams = &aView3d->ChangeRenderingParams();
+    reverse = aParams->ToReverseStereo;
+  }
+  return reverse;
+}
+
+void OCCViewer_ViewWindow::setVSync( bool enable )
+{
+  Handle(AIS_InteractiveContext) anIntCont = myModel->getAISContext();
+  if ( !anIntCont.IsNull() ) {
+    Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast(anIntCont->CurrentViewer()->Driver());
+    OpenGl_Caps* aCaps = &aDriver->ChangeOptions();
+    aCaps->swapInterval = enable;
+  }
+}
+
+bool OCCViewer_ViewWindow::isVSync() const
+{
+  int enable = true;
+  Handle(AIS_InteractiveContext) anIntCont = myModel->getAISContext();
+  if ( !anIntCont.IsNull() ) {
+    Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast(anIntCont->CurrentViewer()->Driver());
+    OpenGl_Caps* aCaps = &aDriver->ChangeOptions();
+    enable = aCaps->swapInterval;
+  }
+  return enable;
+}
+
+void OCCViewer_ViewWindow::setQuadBufferSupport( bool enable )
+{
+  Handle(AIS_InteractiveContext) anIntCont = myModel->getAISContext();
+  if ( !anIntCont.IsNull() ) {
+    Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast(anIntCont->CurrentViewer()->Driver());
+    OpenGl_Caps* aCaps = &aDriver->ChangeOptions();
+    aCaps->contextStereo = enable;
+  }
+}
+
+bool OCCViewer_ViewWindow::isQuadBufferSupport() const
+{
+  int enable = true;
+  Handle(AIS_InteractiveContext) anIntCont = myModel->getAISContext();
+  if ( !anIntCont.IsNull() ) {
+    Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast(anIntCont->CurrentViewer()->Driver());
+    OpenGl_Caps* aCaps = &aDriver->ChangeOptions();
+    enable = aCaps->contextStereo;
+  }
+  return enable;
+}
+
+
+bool OCCViewer_ViewWindow::isOpenGlStereoSupport() const
+{
+  GLboolean support[1];
+  glGetBooleanv (GL_STEREO, support);
+  if ( support[0] )
+    return true;
+  return false;
+}
+
+// obsolete
 QColor OCCViewer_ViewWindow::backgroundColor() const
 {
   return myViewPort ? myViewPort->backgroundColor() : Qt::black;
 }
-   
+
 // obsolete
 void OCCViewer_ViewWindow::setBackgroundColor( const QColor& theColor )
 {
@@ -2602,12 +3340,17 @@ Qtx::BackgroundData OCCViewer_ViewWindow::background() const
 {
   return myViewPort ? myViewPort->background() : Qtx::BackgroundData();
 }
-   
+
 void OCCViewer_ViewWindow::setBackground( const Qtx::BackgroundData& theBackground )
 {
   if ( myViewPort ) myViewPort->setBackground( theBackground );
 }
 
+void OCCViewer_ViewWindow::showStaticTrihedron( bool on )
+{
+  if ( myViewPort ) myViewPort->showStaticTrihedron( on );
+}
+
 /*!
   Clears view aspects
 */
@@ -2661,65 +3404,40 @@ SUIT_CameraProperties OCCViewer_ViewWindow::cameraProperties()
     aProps.setDimension( SUIT_CameraProperties::Dim2D );
     aProps.setViewSide( (SUIT_CameraProperties::ViewSide)(int)get2dMode() );
   }
-  
+
   // read common properites of the view
-  Standard_Real anUpDir[3];
-  Standard_Real aPrjDir[3];
-  Standard_Real aMapScale[2];
-  Standard_Real aTranslation[3];
+  Standard_Real anUp[3];
+  Standard_Real anAt[3];
+  Standard_Real anEye[3];
+  Standard_Real aProj[3];
   Standard_Real anAxialScale[3];
-  
-  aSourceView->Up(anUpDir[0], anUpDir[1], anUpDir[2]);
-  aSourceView->Proj(aPrjDir[0], aPrjDir[1], aPrjDir[2]);
-  aSourceView->At(aTranslation[0], aTranslation[1], aTranslation[2]);
-  aSourceView->Size(aMapScale[0], aMapScale[1]);
-
-  getViewPort()->getAxialScale(anAxialScale[0], anAxialScale[1], anAxialScale[2]);
-
-  // we use similar depth to the one used in perspective projection 
-  // to proivde a convinience synchronization with other camera views that
-  // can switch between orthogonal & perspective projection. otherwise,
-  // the camera will get to close when switching from orthogonal to perspective.
-  Standard_Real aCameraDepth = aSourceView->Depth() + aSourceView->ZSize() * 0.5;
-
-  // store common props
-  aProps.setViewUp(anUpDir[0], anUpDir[1], anUpDir[2]);
-  aProps.setMappingScale(aMapScale[1] / 2.0);
-  aProps.setAxialScale(anAxialScale[0], anAxialScale[1], anAxialScale[2]);
-  
-  // generate view orientation matrix for transforming OCC projection reference point
-  // into a camera (eye) position.
-  gp_Dir aLeftDir = gp_Dir(anUpDir[0], anUpDir[1], anUpDir[2]).Crossed(
-    gp_Dir(aPrjDir[0], aPrjDir[1], aPrjDir[2]));
-
-  gp_Trsf aTrsf;
-  aTrsf.SetValues( aLeftDir.X(), anUpDir[0], aPrjDir[0], aTranslation[0],
-                   aLeftDir.Y(), anUpDir[1], aPrjDir[1], aTranslation[1],
-                   aLeftDir.Z(), anUpDir[2], aPrjDir[2], aTranslation[2],
-                   Precision::Confusion(),
-                   Precision::Confusion() );
-
-// get projection reference point in view coordinates
-#if OCC_VERSION_LARGE > 0x06070000
-  gp_Pnt aProjRef = aSourceView->Camera()->ProjectionShift();
-  aProjRef.SetX( -aProjRef.X() );
-  aProjRef.SetY( -aProjRef.Y() );
-#else
-  Graphic3d_Vertex aProjRef = aSourceView->ViewMapping().ProjectionReferencePoint();
-#endif
 
-  // transform to world-space coordinate system
-  gp_Pnt aPosition = gp_Pnt(aProjRef.X(), aProjRef.Y(), aCameraDepth).Transformed(aTrsf);
-  
-  // compute focal point
-  double aFocalPoint[3];
+  aSourceView->Up( anUp[0], anUp[1], anUp[2] );
+  aSourceView->At( anAt[0], anAt[1], anAt[2] );
+  aSourceView->Proj( aProj[0], aProj[1], aProj[2] );
+  getViewPort()->getAxialScale( anAxialScale[0], anAxialScale[1], anAxialScale[2] );
+
+  aProps.setAxialScale( anAxialScale[0], anAxialScale[1], anAxialScale[2] );
+  aProps.setViewUp( anUp[0], anUp[1], anUp[2] );
 
-  aFocalPoint[0] = aPosition.X() - aPrjDir[0] * aCameraDepth;
-  aFocalPoint[1] = aPosition.Y() - aPrjDir[1] * aCameraDepth;
-  aFocalPoint[2] = aPosition.Z() - aPrjDir[2] * aCameraDepth;
+  aSourceView->Eye( anEye[0], anEye[1], anEye[2] );
 
-  aProps.setFocalPoint(aFocalPoint[0], aFocalPoint[1], aFocalPoint[2]);
-  aProps.setPosition(aPosition.X(), aPosition.Y(), aPosition.Z());
+  // store camera properties "as is": it is up to synchronized
+  // view classes to provide necessary property conversion.
+  aProps.setPosition( anEye[0], anEye[1], anEye[2] );
+  aProps.setFocalPoint( anAt[0], anAt[1], anAt[2] );
+
+  if ( aSourceView->Camera()->IsOrthographic() )
+  {
+    aProps.setProjection( SUIT_CameraProperties::PrjOrthogonal );
+    aProps.setViewAngle( 0.0 );
+  }
+  else
+  {
+    aProps.setProjection( SUIT_CameraProperties::PrjPerspective );
+    aProps.setViewAngle( aSourceView->Camera()->FOVy() );
+  }
+  aProps.setMappingScale( aSourceView->Camera()->Scale() );
 
   return aProps;
 }
@@ -2747,79 +3465,20 @@ void OCCViewer_ViewWindow::synchronize( SUIT_ViewWindow* theView )
   double anUpDir[3];
   double aPosition[3];
   double aFocalPoint[3];
-  double aMapScaling;
   double anAxialScale[3];
 
   // get common properties
-  aProps.getFocalPoint(aFocalPoint[0], aFocalPoint[1], aFocalPoint[2]);
-  aProps.getPosition(aPosition[0], aPosition[1], aPosition[2]);
-  aProps.getViewUp(anUpDir[0], anUpDir[1], anUpDir[2]);
-  aProps.getAxialScale(anAxialScale[0], anAxialScale[1], anAxialScale[2]);
-  aMapScaling = aProps.getMappingScale() * 2.0;
-
-  gp_Dir aProjDir(aPosition[0] - aFocalPoint[0],
-                  aPosition[1] - aFocalPoint[1],
-                  aPosition[2] - aFocalPoint[2]);
-  
-  // get custom view translation
-  Standard_Real aTranslation[3];
-  aDestView->At(aTranslation[0], aTranslation[1], aTranslation[2]);
-
-  gp_Dir aLeftDir = gp_Dir(anUpDir[0], anUpDir[1], anUpDir[2]).Crossed(
-    gp_Dir(aProjDir.X(), aProjDir.Y(), aProjDir.Z()));
-
-  // convert camera position into a view reference point
-  gp_Trsf aTrsf;
-  aTrsf.SetValues( aLeftDir.X(), anUpDir[0], aProjDir.X(), aTranslation[0],
-                   aLeftDir.Y(), anUpDir[1], aProjDir.Y(), aTranslation[1],
-                   aLeftDir.Z(), anUpDir[2], aProjDir.Z(), aTranslation[2], 
-                   Precision::Confusion(),
-                   Precision::Confusion() );
-  aTrsf.Invert();
-
-  // transform to view-space coordinate system
-  gp_Pnt aProjRef(aPosition[0], aPosition[1], aPosition[2]);
-  aProjRef.Transform(aTrsf);
-
-#if OCC_VERSION_LARGE > 0x06070000
-  aDestView->Camera()->SetDirection( -aProjDir );
-  aDestView->Camera()->SetUp( gp_Dir( anUpDir[0], anUpDir[1], anUpDir[2] ) );
-  aDestView->Camera()->SetProjectionShift( gp_Pnt( -aProjRef.X(), -aProjRef.Y(), 0.0 ) );
-#else
-  // set view camera properties using low-level approach. this is done
-  // in order to avoid interference with static variables in v3d view used
-  // when rotation is in process in another view.
-  Visual3d_ViewMapping aMapping = aDestView->View()->ViewMapping();
-  Visual3d_ViewOrientation anOrientation = aDestView->View()->ViewOrientation();
-
-  Graphic3d_Vector aMappingProj(aProjDir.X(), aProjDir.Y(), aProjDir.Z());
-  Graphic3d_Vector aMappingUp(anUpDir[0], anUpDir[1], anUpDir[2]);
-
-  aMappingProj.Normalize();
-  aMappingUp.Normalize();
+  aProps.getFocalPoint( aFocalPoint[0], aFocalPoint[1], aFocalPoint[2] );
+  aProps.getPosition( aPosition[0], aPosition[1], aPosition[2] );
+  aProps.getViewUp( anUpDir[0], anUpDir[1], anUpDir[2] );
+  aProps.getAxialScale( anAxialScale[0], anAxialScale[1], anAxialScale[2] );
 
-  anOrientation.SetViewReferencePlane(aMappingProj);
-  anOrientation.SetViewReferenceUp(aMappingUp);
-
-  aDestView->SetViewMapping(aMapping);
-  aDestView->SetViewOrientation(anOrientation);
-
-  // set panning
-  aDestView->SetCenter(aProjRef.X(), aProjRef.Y());
-#endif
+  aDestView->SetAt( aFocalPoint[0], aFocalPoint[1], aFocalPoint[2] );
+  aDestView->SetEye( aPosition[0], aPosition[1], aPosition[2] );
+  aDestView->SetUp( anUpDir[0], anUpDir[1], anUpDir[2] );
+  aDestView->Camera()->SetScale( aProps.getMappingScale() );
 
-  // set mapping scale
-  Standard_Real aWidth, aHeight;
-  aDestView->Size(aWidth, aHeight);
-  
-  if ( aWidth > aHeight )
-    aDestView->SetSize (aMapScaling * (aWidth / aHeight));
-  else
-    aDestView->SetSize (aMapScaling);
-
-  getViewPort()->setAxialScale(anAxialScale[0], anAxialScale[1], anAxialScale[2]);
-
-  aDestView->ZFitAll();
+  getViewPort()->setAxialScale( anAxialScale[0], anAxialScale[1], anAxialScale[2] );
   aDestView->SetImmediateUpdate( Standard_True );
   aDestView->Redraw();
 
@@ -2874,7 +3533,7 @@ void OCCViewer_ViewWindow::onClipping (bool theIsOn)
 {
   if(!myModel) return;
   OCCViewer_ClippingDlg* aClippingDlg = myModel->getClippingDlg();
-  
+
   if (theIsOn) {
     if (!aClippingDlg) {
       aClippingDlg = new OCCViewer_ClippingDlg (this, myModel);
@@ -2907,3 +3566,30 @@ void OCCViewer_ViewWindow::onClipping (bool theIsOn)
     }
   }
 }
+
+void OCCViewer_ViewWindow::onRayTracing()
+{
+  if( !OCCViewer_Utilities::isDialogOpened( this, OCCViewer_RayTracingDlg::getName() ) ) {
+    QDialog* aDlg = new OCCViewer_RayTracingDlg( this );
+    if ( aDlg != NULL )
+      aDlg->show();
+  }
+}
+
+void OCCViewer_ViewWindow::onEnvTexture()
+{
+  if( !OCCViewer_Utilities::isDialogOpened( this, OCCViewer_EnvTextureDlg::getName() ) ) {
+    QDialog* aDlg = new OCCViewer_EnvTextureDlg( this );
+    if ( aDlg != NULL )
+      aDlg->show();
+  }
+}
+
+void OCCViewer_ViewWindow::onLightSource()
+{
+  if( !OCCViewer_Utilities::isDialogOpened( this, OCCViewer_LightSourceDlg::getName() ) ) {
+    QDialog* aDlg = new OCCViewer_LightSourceDlg( this, myModel );
+    if ( aDlg != NULL )
+      aDlg->show();
+  }
+}