]> OCCT Git - occt-copy.git/commitdiff
0031644: Visualization - flat skin for AIS_Manipulator presentation CR31644_1
authormzernova <mzernova@opencascade.com>
Fri, 25 Sep 2020 14:53:09 +0000 (17:53 +0300)
committermzernova <mzernova@opencascade.com>
Fri, 23 Oct 2020 12:20:20 +0000 (15:20 +0300)
Created flat skin for AIS_Manipulator presentation
Added "-flat" option to vmanipulator command

Added functionality to transform the manipulator depending on the camera rotation.

Added local transformation for Graphic3d_Group.

Added RecomputeTransformation method to PrsMgr_PresentableObject.
When overloading this method, you can set a transformation for an object depending on the rotation of the camera.

v3d/manipulator/flat: test case added

14 files changed:
src/AIS/AIS_InteractiveContext.cxx
src/AIS/AIS_Manipulator.cxx
src/AIS/AIS_Manipulator.hxx
src/AIS/AIS_ViewController.cxx
src/Graphic3d/Graphic3d_CView.cxx
src/Graphic3d/Graphic3d_Group.hxx
src/Graphic3d/Graphic3d_Structure.hxx
src/OpenGl/OpenGl_Structure.cxx
src/OpenGl/OpenGl_Structure.hxx
src/PrsMgr/PrsMgr_PresentableObject.hxx
src/PrsMgr/PrsMgr_Presentation.cxx
src/PrsMgr/PrsMgr_Presentation.hxx
src/ViewerTest/ViewerTest_ViewerCommands.cxx
tests/v3d/manipulator/flat [new file with mode: 0644]

index 67fece1c1f499d89fa346cada6b7402f93e89869..a3cbfd3e3118abb81e1c2c0017652f3429c11640 100644 (file)
@@ -1002,7 +1002,13 @@ void AIS_InteractiveContext::RecomputePrsOnly (const Handle(AIS_InteractiveObjec
   {
     myMainVwr->Update();
   }
+
+  if (!myMainVwr->ActiveViews().IsEmpty())
+  {
+    theIObj->RecomputeTransformation (myMainVwr->ActiveViewIterator().Value()->Camera());
+  }
 }
+
 //=======================================================================
 //function : RecomputeSelectionOnly
 //purpose  : 
index 53d75ed00030e3b2a77e86504550eca93bbef375..6436db0dd3845fadef5a29b4cd4f294614f91ca2 100644 (file)
@@ -225,6 +225,7 @@ AIS_Manipulator::AIS_Manipulator()
   myCurrentMode (AIS_MM_None),
   myIsActivationOnDetection (Standard_False),
   myIsZoomPersistentMode (Standard_True),
+  mySkinMode (ManipulatorSkin_Shaded),
   myHasStartedTransformation (Standard_False),
   myStartPosition (gp::XOY()),
   myStartPick (0.0, 0.0, 0.0),
@@ -246,6 +247,7 @@ AIS_Manipulator::AIS_Manipulator (const gp_Ax2& thePosition)
   myCurrentMode (AIS_MM_None),
   myIsActivationOnDetection (Standard_False),
   myIsZoomPersistentMode (Standard_True),
+  mySkinMode (ManipulatorSkin_Shaded),
   myHasStartedTransformation (Standard_False),
   myStartPosition (gp::XOY()),
   myStartPick (0.0, 0.0, 0.0),
@@ -585,16 +587,33 @@ Standard_Boolean AIS_Manipulator::ObjectTransformation (const Standard_Integer t
       gp_Dir aCurrentAxis = gce_MakeDir (aPosLoc, aNewPosition);
       Standard_Real anAngle = aStartAxis.AngleWithRef (aCurrentAxis, aCurrAxis.Direction());
 
-      // Change value of an angle if it should have different sign.
-      if (anAngle * myPrevState < 0 && Abs (anAngle) < M_PI_2)
+      if (Abs (anAngle) < Precision::Confusion())
       {
-        Standard_Real aSign = myPrevState > 0 ? -1.0 : 1.0;
-        anAngle = aSign * (M_PI * 2 - anAngle);
+        return Standard_False;
       }
 
-      if (Abs (anAngle) < Precision::Confusion())
+      // Draw a sector indicating the rotation angle
+      if (mySkinMode == ManipulatorSkin_Flat)
       {
-        return Standard_False;
+        const gp_Ax1& anAxis = myAxes[myCurrentIndex].ReferenceAxis();
+        const gp_Dir aRotationStart = anAxis.Direction().Z() > 0 ? myStartPosition.YDirection() : myStartPosition.Direction();
+        Standard_Real aRotationAngle = aRotationStart.AngleWithRef (aCurrentAxis, aCurrAxis.Direction());
+        aRotationAngle -= (anAngle > 0) ? anAngle * 2.0 : anAngle;
+        if (anAxis.Direction().Z() > 0) { aRotationAngle += M_PI_2; }
+
+        gp_Trsf aTrsf;
+        aTrsf.SetRotation (anAxis, aRotationAngle);
+
+        Handle(Prs3d_ShadingAspect) anAspect = new Prs3d_ShadingAspect();
+        anAspect->SetMaterial (myDrawer->ShadingAspect()->Material());
+        anAspect->SetTransparency (0.5);
+        anAspect->SetColor (myAxes[myCurrentIndex].Color());
+
+        mySector.Init (0.0f, myAxes[myCurrentIndex].InnerRadius(), anAxis, Abs (anAngle));
+        mySectorGroup->Clear();
+        mySectorGroup->SetPrimitivesAspect (anAspect->Aspect());
+        mySectorGroup->AddPrimitiveArray (mySector.Array());
+        mySectorGroup->SetTransformation (aTrsf);
       }
 
       gp_Trsf aNewTrsf;
@@ -672,7 +691,10 @@ Standard_Boolean AIS_Manipulator::ProcessDragging (const Handle(AIS_InteractiveC
       return Standard_True;
     }
     case AIS_DragAction_Stop:
+    {
+      if (mySkinMode == ManipulatorSkin_Flat) { mySectorGroup->Clear(); }
       break;
+    }
   }
   return Standard_False;
 }
@@ -719,6 +741,173 @@ void AIS_Manipulator::StopTransform (const Standard_Boolean theToApply)
   SetPosition (myStartPosition);
 }
 
+//=======================================================================
+//function : RecomputeTransformation
+//purpose  :
+//=======================================================================
+void AIS_Manipulator::RecomputeTransformation (const Handle(Graphic3d_Camera)& theCamera)
+{
+  if (mySkinMode == ManipulatorSkin_Shaded)
+  {
+    return;
+  }
+
+  Standard_Boolean isRecomputedTranslation = Standard_False;
+  Standard_Boolean isRecomputedRotation = Standard_False;
+  Standard_Boolean isRecomputedDragging = Standard_False;
+  Standard_Boolean isRecomputedScaling = Standard_False;
+
+  // Remove transformation from dragger group
+  for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
+  {
+    if (myAxes[anIt].HasDragging())
+    {
+      myAxes[anIt].DraggerGroup()->SetTransformation (gp_Trsf());
+      isRecomputedDragging = Standard_True;
+    }
+  }
+
+  const gp_Dir& aCameraDir = theCamera->Direction();
+  for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
+  {
+    const gp_Ax1& anAxis = myAxes[anIt].ReferenceAxis();
+    gp_Dir anAxisDir, aNormal;
+
+    if (anAxis.Direction().X() > 0)
+    {
+      aNormal = myPosition.YDirection().Reversed();
+      anAxisDir = myPosition.XDirection();
+    }
+    else if (anAxis.Direction().Y() > 0)
+    {
+      aNormal = myPosition.XDirection().Crossed (myPosition.YDirection()).Reversed();
+      anAxisDir = myPosition.YDirection();
+    }
+    else
+    {
+      aNormal = myPosition.XDirection().Reversed();
+      anAxisDir = myPosition.XDirection().Crossed (myPosition.YDirection());
+    }
+
+    const gp_Dir aCameraProj = Abs (Abs (anAxisDir.Dot (aCameraDir)) - 1.0) <= gp::Resolution()
+      ? aCameraDir
+      : anAxisDir.Crossed (aCameraDir).Crossed (anAxisDir);
+    const Standard_Boolean isReversed = anAxisDir.Dot (aCameraDir) > 0;
+    Standard_Real anAngle = aNormal.AngleWithRef (aCameraProj, anAxisDir);
+    if (anAxis.Direction().X() > 0) anAngle -= M_PI_2;
+
+    if (myAxes[anIt].HasTranslation())
+    {
+      Handle(Prs3d_ShadingAspect) anAspect = new Prs3d_ShadingAspect();
+
+      Graphic3d_MaterialAspect& aMat = anAspect->Aspect()->ChangeFrontMaterial();
+      Quantity_Color aColor = isReversed
+        ? Quantity_Color (myAxes[anIt].Color().Rgb() * 0.05f)
+        : myAxes[anIt].Color();
+      aMat.SetAmbientColor (aColor);
+      aMat.SetDiffuseColor (aColor);
+      aMat.SetSpecularColor (aColor);
+      aMat.SetEmissiveColor (aColor);
+
+      gp_Trsf aTranslatorTrsf;
+      aTranslatorTrsf.SetRotation (anAxis, anAngle);
+      if (isReversed)
+      {
+        const Standard_Real aLength = myAxes[anIt].AxisLength() + myAxes[anIt].Indent() * 4.0f;
+        aTranslatorTrsf.SetTranslationPart (anAxis.Direction().XYZ().Reversed() * aLength);
+      }
+
+      myAxes[anIt].TranslatorGroup()->SetGroupPrimitivesAspect (anAspect->Aspect());
+      myAxes[anIt].TranslatorGroup()->SetTransformation (aTranslatorTrsf);
+      myAxes[anIt].TranslatorHighlightPrs()->CurrentGroup()->SetTransformation (aTranslatorTrsf);
+      isRecomputedTranslation = Standard_True;
+    }
+
+    if (myAxes[anIt].HasRotation())
+    {
+      gp_Trsf aRotatorTrsf;
+      aRotatorTrsf.SetRotation (anAxis, anAngle - M_PI_2);
+      myAxes[anIt].RotatorGroup()->SetTransformation (aRotatorTrsf);
+      myAxes[anIt].RotatorHighlightPrs()->CurrentGroup()->SetTransformation (aRotatorTrsf);
+      isRecomputedRotation = Standard_True;
+    }
+
+    if (myAxes[anIt].HasDragging() && isReversed)
+    {
+      for (Standard_Integer anIndexIter = 0; anIndexIter < 3; ++anIndexIter)
+      {
+        const Handle(Graphic3d_Group)& aDraggerGroup = myAxes[anIndexIter].DraggerGroup();
+        gp_Vec aTranslation = (anIndexIter == anIt)
+          ? anAxis.Direction().XYZ() * myAxes[anIndexIter].AxisRadius() * 2.0f
+          : anAxis.Direction().XYZ().Reversed() * myAxes[anIndexIter].AxisLength();
+        gp_Trsf aDraggerTrsf;
+        aDraggerTrsf.SetTranslation (aTranslation);
+        aDraggerTrsf *= aDraggerGroup->Transformation();
+        aDraggerGroup->SetTransformation (aDraggerTrsf);
+      }
+    }
+
+    if (myAxes[anIt].HasScaling())
+    {
+      gp_Trsf aScalerTrsf;
+      if (anAxis.Direction().X() > 0) { anAngle += M_PI_2; }
+      aScalerTrsf.SetRotation (anAxis, anAngle);
+      if (isReversed)
+      {
+        Standard_ShortReal aLength = myAxes[anIt].AxisLength() * 2.0f + myAxes[anIt].BoxSize() + myAxes[anIt].Indent() * 4.0f;
+        aScalerTrsf.SetTranslationPart (gp_Vec (anAxis.Direction().XYZ().Reversed() * aLength));
+      }
+      myAxes[anIt].ScalerGroup()->SetTransformation (aScalerTrsf);
+      myAxes[anIt].ScalerHighlightPrs()->CurrentGroup()->SetTransformation (aScalerTrsf);
+      isRecomputedScaling = Standard_True;
+    }
+  }
+
+  if (isRecomputedRotation)
+  {
+    const gp_Dir aXDir = gp::DX();
+    const gp_Dir anYDir = gp::DY();
+    const gp_Dir aZDir = gp::DZ();
+
+    const gp_Dir aCameraProjection = Abs (aXDir.Dot (aCameraDir)) <= gp::Resolution() || Abs (anYDir.Dot (aCameraDir)) <= gp::Resolution()
+      ? aCameraDir
+      : aXDir.XYZ() * (aXDir.Dot (aCameraDir)) + anYDir.XYZ() * (anYDir.Dot (aCameraDir));
+    const Standard_Boolean isReversed = aZDir.Dot (aCameraDir) > 0;
+
+    const Standard_Real anAngle = M_PI_2 - aCameraDir.Angle (aCameraProjection);
+    gp_Dir aRotAxis = Abs (Abs (aCameraProjection.Dot (aZDir)) - 1.0) <= gp::Resolution()
+      ? aZDir
+      : aCameraProjection.Crossed (aZDir);
+    if (isReversed) { aRotAxis.Reverse(); }
+
+    gp_Trsf aRotationTrsf;
+    aRotationTrsf.SetRotation (gp_Ax1 (gp::Origin(), aRotAxis), anAngle);
+
+    gp_Ax3 aToSystem (gp::Origin(), myPosition.XDirection().Crossed (myPosition.YDirection()), myPosition.XDirection());
+    gp_Ax3 aFromSystem (gp::XOY());
+    aFromSystem.Transform (aRotationTrsf);
+
+    gp_Trsf aTrsf;
+    aTrsf.SetTransformation (aFromSystem, aToSystem);
+    myCircleGroup->SetTransformation (aTrsf);
+  }
+
+  if (isRecomputedDragging)
+  {
+    for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
+    {
+      myAxes[anIt].DraggerHighlightPrs()->CurrentGroup()->SetTransformation (myAxes[anIt].DraggerGroup()->Transformation());
+    }
+  }
+
+  if (isRecomputedTranslation) { RecomputeSelection (AIS_MM_Translation); };
+  if (isRecomputedRotation) { RecomputeSelection (AIS_MM_Rotation); };
+  if (isRecomputedDragging) { RecomputeSelection (AIS_MM_TranslationPlane); };
+  if (isRecomputedScaling) { RecomputeSelection (AIS_MM_Scaling); };
+
+  Object()->GetContext()->RecomputeSelectionOnly (this);
+}
+
 //=======================================================================
 //function : Transform
 //purpose  : 
@@ -924,6 +1113,19 @@ void AIS_Manipulator::SetZoomPersistence (const Standard_Boolean theToEnable)
   updateTransformation();
 }
 
+//=======================================================================
+//function : SetSkinMode
+//purpose  :
+//=======================================================================
+void AIS_Manipulator::SetSkinMode (const ManipulatorSkin theSkinMode)
+{
+  if (mySkinMode != theSkinMode)
+  {
+    SetToUpdate();
+  }
+  mySkinMode = theSkinMode;
+}
+
 //=======================================================================
 //function : SetTransformPersistence
 //purpose  :
@@ -983,11 +1185,26 @@ void AIS_Manipulator::Compute (const Handle(PrsMgr_PresentationManager3d)& thePr
   anAspect->SetTransparency (myDrawer->ShadingAspect()->Transparency());
 
   // Display center
-  myCenter.Init (myAxes[0].AxisRadius() * 2.0f, gp::Origin());
+  myCenter.Init (myAxes[0].AxisRadius() * 2.0f, gp::Origin(), mySkinMode);
   aGroup = thePrs->NewGroup ();
   aGroup->SetPrimitivesAspect (myDrawer->ShadingAspect()->Aspect());
   aGroup->AddPrimitiveArray (myCenter.Array());
 
+  // Display outer circle
+  if (mySkinMode == ManipulatorSkin_Flat
+   && (myAxes[0].HasRotation() || myAxes[1].HasRotation() || myAxes[2].HasRotation()))
+  {
+    myCircle.Init (myAxes[0].InnerRadius(), myAxes[0].Size(),
+                   gp_Ax1 (gp::Origin(), gp::DZ()),
+                   2.0f * M_PI, myAxes[0].FacettesNumber() * 4);
+    myCircleGroup = thePrs->NewGroup ();
+    myCircleGroup->SetPrimitivesAspect (myDrawer->ShadingAspect()->Aspect());
+    myCircleGroup->AddPrimitiveArray (myCircle.Array());
+
+    mySectorGroup = thePrs->NewGroup ();
+    mySectorGroup->SetGroupPrimitivesAspect (anAspect->Aspect());
+  }
+
   for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
   {
     // Display axes
@@ -996,7 +1213,7 @@ void AIS_Manipulator::Compute (const Handle(PrsMgr_PresentationManager3d)& thePr
     Handle(Prs3d_ShadingAspect) anAspectAx = new Prs3d_ShadingAspect (new Graphic3d_AspectFillArea3d(*anAspect->Aspect()));
     anAspectAx->SetColor (myAxes[anIt].Color());
     aGroup->SetGroupPrimitivesAspect (anAspectAx->Aspect());
-    myAxes[anIt].Compute (thePrsMgr, thePrs, anAspectAx);
+    myAxes[anIt].Compute (thePrsMgr, thePrs, anAspectAx, mySkinMode);
     myAxes[anIt].SetTransformPersistence (TransformPersistence());
   }
 
@@ -1034,7 +1251,7 @@ void AIS_Manipulator::HilightSelected (const Handle(PrsMgr_PresentationManager3d
     return;
   }
 
-  if (anOwner->Mode() == AIS_MM_TranslationPlane)
+  if (anOwner->Mode() == AIS_MM_TranslationPlane && mySkinMode == ManipulatorSkin_Shaded)
   {
     myDraggerHighlight->SetColor(myAxes[anOwner->Index()].Color());
     aGroup->SetGroupPrimitivesAspect(myDraggerHighlight->Aspect());
@@ -1072,7 +1289,7 @@ void AIS_Manipulator::HilightOwnerWithColor (const Handle(PrsMgr_PresentationMan
 
   aPresentation->CStructure()->ViewAffinity = thePM->StructureManager()->ObjectAffinity (Handle(Standard_Transient) (this));
 
-  if (anOwner->Mode() == AIS_MM_TranslationPlane)
+  if (anOwner->Mode() == AIS_MM_TranslationPlane && mySkinMode == ManipulatorSkin_Shaded)
   {
     Handle(Prs3d_Drawer) aStyle = new Prs3d_Drawer();
     aStyle->SetColor (myAxes[anOwner->Index()].Color());
@@ -1108,6 +1325,25 @@ void AIS_Manipulator::HilightOwnerWithColor (const Handle(PrsMgr_PresentationMan
   }
 }
 
+//=======================================================================
+//function : RecomputeSelection
+//purpose  : 
+//=======================================================================
+void AIS_Manipulator::RecomputeSelection (const AIS_ManipulatorMode theMode)
+{
+  if (theMode == AIS_MM_None)
+  {
+    return;
+  }
+
+  const Handle(SelectMgr_Selection)& aSelection = Object()->Selection (theMode);
+  if (!aSelection.IsNull())
+  {
+    aSelection->Clear();
+    ComputeSelection (aSelection, theMode);
+  }
+}
+
 //=======================================================================
 //function : ComputeSelection
 //purpose  : 
@@ -1121,13 +1357,9 @@ void AIS_Manipulator::ComputeSelection (const Handle(SelectMgr_Selection)& theSe
   {
     return;
   }
-  Handle(SelectMgr_EntityOwner) anOwner;
-  if (aMode == AIS_MM_None)
-  {
-    anOwner = new SelectMgr_EntityOwner (this, 5);
-  }
 
-  if (aMode == AIS_MM_Translation || aMode == AIS_MM_None)
+  Handle(SelectMgr_EntityOwner) anOwner;
+  if (aMode == AIS_MM_Translation)
   {
     for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
     {
@@ -1136,23 +1368,27 @@ void AIS_Manipulator::ComputeSelection (const Handle(SelectMgr_Selection)& theSe
         continue;
       }
       const Axis& anAxis = myAxes[anIt];
-      if (aMode != AIS_MM_None)
+      anOwner = new AIS_ManipulatorOwner (this, anIt, AIS_MM_Translation, 9);
+
+      if (mySkinMode == ManipulatorSkin_Shaded)
       {
-        anOwner = new AIS_ManipulatorOwner (this, anIt, AIS_MM_Translation, 9);
+        // define sensitivity by line
+        Handle(Select3D_SensitiveSegment) aLine = new Select3D_SensitiveSegment (anOwner, gp::Origin(), anAxis.TranslatorTipPosition());
+        aLine->SetSensitivityFactor (15);
+        theSelection->Add (aLine);
       }
-      // define sensitivity by line
-      Handle(Select3D_SensitiveSegment) aLine = new Select3D_SensitiveSegment (anOwner, gp::Origin(), anAxis.TranslatorTipPosition());
-      aLine->SetSensitivityFactor (15);
-      theSelection->Add (aLine);
 
       // enlarge sensitivity by triangulation
       Handle(Select3D_SensitivePrimitiveArray) aTri = new Select3D_SensitivePrimitiveArray (anOwner);
-      aTri->InitTriangulation (anAxis.TriangleArray()->Attributes(), anAxis.TriangleArray()->Indices(), TopLoc_Location());
+      TopLoc_Location aTrsf = !myAxes[anIt].TranslatorGroup().IsNull()
+        ? TopLoc_Location (myAxes[anIt].TranslatorGroup()->Transformation())
+        : TopLoc_Location();
+      aTri->InitTriangulation (anAxis.TriangleArray()->Attributes(), anAxis.TriangleArray()->Indices(), aTrsf);
       theSelection->Add (aTri);
     }
   }
 
-  if (aMode == AIS_MM_Rotation || aMode == AIS_MM_None)
+  if (aMode == AIS_MM_Rotation)
   {
     for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
     {
@@ -1161,22 +1397,28 @@ void AIS_Manipulator::ComputeSelection (const Handle(SelectMgr_Selection)& theSe
         continue;
       }
       const Axis& anAxis = myAxes[anIt];
-      if (aMode != AIS_MM_None)
+      anOwner = new AIS_ManipulatorOwner (this, anIt, AIS_MM_Rotation, 9);
+
+      if (mySkinMode == ManipulatorSkin_Shaded)
       {
-        anOwner = new AIS_ManipulatorOwner (this, anIt, AIS_MM_Rotation, 9);
+        // define sensitivity by circle
+        const gp_Circ aGeomCircle (gp_Ax2 (gp::Origin(), anAxis.ReferenceAxis().Direction()), anAxis.RotatorDiskRadius());
+        Handle(Select3D_SensitiveCircle) aCircle = new ManipSensCircle (anOwner, aGeomCircle, anAxis.FacettesNumber());
+        aCircle->SetSensitivityFactor (15);
+        theSelection->Add (aCircle);
       }
-      // define sensitivity by circle
-      const gp_Circ aGeomCircle (gp_Ax2 (gp::Origin(), anAxis.ReferenceAxis().Direction()), anAxis.RotatorDiskRadius());
-      Handle(Select3D_SensitiveCircle) aCircle = new ManipSensCircle (anOwner, aGeomCircle, anAxis.FacettesNumber());
-      aCircle->SetSensitivityFactor (15);
-      theSelection->Add (aCircle);
       // enlarge sensitivity by triangulation
-      Handle(Select3D_SensitiveTriangulation) aTri = new ManipSensTriangulation (anOwner, myAxes[anIt].RotatorDisk().Triangulation(), anAxis.ReferenceAxis().Direction());
+      Handle(Select3D_SensitivePrimitiveArray) aTri = new Select3D_SensitivePrimitiveArray (anOwner);
+      const Handle(Graphic3d_Group)& aGroup = myAxes[anIt].RotatorGroup();
+      TopLoc_Location aTrsf = !aGroup.IsNull()
+        ? TopLoc_Location (aGroup->Transformation())
+        : TopLoc_Location();
+      aTri->InitTriangulation (myAxes[anIt].RotatorDisk().Array()->Attributes(), myAxes[anIt].RotatorDisk().Array()->Indices(), aTrsf);
       theSelection->Add (aTri);
     }
   }
 
-  if (aMode == AIS_MM_Scaling || aMode == AIS_MM_None)
+  if (aMode == AIS_MM_Scaling)
   {
     for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
     {
@@ -1184,21 +1426,27 @@ void AIS_Manipulator::ComputeSelection (const Handle(SelectMgr_Selection)& theSe
       {
         continue;
       }
-      if (aMode != AIS_MM_None)
+      anOwner = new AIS_ManipulatorOwner (this, anIt, AIS_MM_Scaling, 9);
+
+      if (mySkinMode == ManipulatorSkin_Shaded)
       {
-        anOwner = new AIS_ManipulatorOwner (this, anIt, AIS_MM_Scaling, 9);
+        // define sensitivity by point
+        Handle(Select3D_SensitivePoint) aPnt = new Select3D_SensitivePoint (anOwner, myAxes[anIt].ScalerCubePosition());
+        aPnt->SetSensitivityFactor (15);
+        theSelection->Add (aPnt);
       }
-      // define sensitivity by point
-      Handle(Select3D_SensitivePoint) aPnt = new Select3D_SensitivePoint (anOwner, myAxes[anIt].ScalerCubePosition());
-      aPnt->SetSensitivityFactor (15);
-      theSelection->Add (aPnt);
       // enlarge sensitivity by triangulation
-      Handle(Select3D_SensitiveTriangulation) aTri = new Select3D_SensitiveTriangulation (anOwner, myAxes[anIt].ScalerCube().Triangulation(), TopLoc_Location(), Standard_True);
+      Handle(Select3D_SensitivePrimitiveArray) aTri = new Select3D_SensitivePrimitiveArray (anOwner);
+      const Handle(Graphic3d_Group)& aGroup = myAxes[anIt].ScalerGroup();
+      TopLoc_Location aTrsf = !aGroup.IsNull()
+        ? TopLoc_Location (aGroup->Transformation())
+        : TopLoc_Location();
+      aTri->InitTriangulation (myAxes[anIt].ScalerCube().Array()->Attributes(), myAxes[anIt].ScalerCube().Array()->Indices(), aTrsf);
       theSelection->Add (aTri);
     }
   }
 
-  if (aMode == AIS_MM_TranslationPlane || aMode == AIS_MM_None)
+  if (aMode == AIS_MM_TranslationPlane)
   {
     for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
     {
@@ -1206,27 +1454,32 @@ void AIS_Manipulator::ComputeSelection (const Handle(SelectMgr_Selection)& theSe
       {
         continue;
       }
-      if (aMode != AIS_MM_None)
+      anOwner = new AIS_ManipulatorOwner(this, anIt, AIS_MM_TranslationPlane, 9);
+
+      if (mySkinMode == ManipulatorSkin_Shaded)
       {
-        anOwner = new AIS_ManipulatorOwner(this, anIt, AIS_MM_TranslationPlane, 9);
+        // define sensitivity by two crossed lines
+        gp_Pnt aP1, aP2;
+        aP1 = myAxes[((anIt + 1) % 3)].TranslatorTipPosition();
+        aP2 = myAxes[((anIt + 2) % 3)].TranslatorTipPosition();
+        gp_XYZ aMidP = (aP1.XYZ() + aP2.XYZ()) / 2.0;
+
+        Handle(Select3D_SensitiveSegment) aLine1 = new Select3D_SensitiveSegment(anOwner, aP1, aP2);
+        aLine1->SetSensitivityFactor(10);
+        theSelection->Add(aLine1);
+        Handle(Select3D_SensitiveSegment) aLine2 = new Select3D_SensitiveSegment(anOwner, gp::Origin(), aMidP);
+        aLine2->SetSensitivityFactor(10);
+        theSelection->Add(aLine2);
       }
 
-      // define sensitivity by two crossed lines
-      gp_Pnt aP1, aP2;
-      aP1 = myAxes[((anIt + 1) % 3)].TranslatorTipPosition();
-      aP2 = myAxes[((anIt + 2) % 3)].TranslatorTipPosition();
-      gp_XYZ aMidP = (aP1.XYZ() + aP2.XYZ()) / 2.0;
-
-      Handle(Select3D_SensitiveSegment) aLine1 = new Select3D_SensitiveSegment(anOwner, aP1, aP2);
-      aLine1->SetSensitivityFactor(10);
-      theSelection->Add(aLine1);
-      Handle(Select3D_SensitiveSegment) aLine2 = new Select3D_SensitiveSegment(anOwner, gp::Origin(), aMidP);
-      aLine2->SetSensitivityFactor(10);
-      theSelection->Add(aLine2);
-
       // enlarge sensitivity by triangulation
-      Handle(Select3D_SensitiveTriangulation) aTri = new Select3D_SensitiveTriangulation(anOwner, myAxes[anIt].DraggerSector().Triangulation(), TopLoc_Location(), Standard_True);
-      theSelection->Add(aTri);
+      Handle(Select3D_SensitivePrimitiveArray) aTri = new Select3D_SensitivePrimitiveArray (anOwner);
+      const Handle(Graphic3d_Group)& aGroup = myAxes[anIt].DraggerGroup();
+      TopLoc_Location aTrsf = !aGroup.IsNull()
+        ? TopLoc_Location (aGroup->Transformation())
+        : TopLoc_Location();
+      aTri->InitTriangulation (myAxes[anIt].DraggerSector().Array()->Attributes(), myAxes[anIt].DraggerSector().Array()->Indices(), aTrsf);
+      theSelection->Add (aTri);
     }
   }
 }
@@ -1238,15 +1491,17 @@ void AIS_Manipulator::ComputeSelection (const Handle(SelectMgr_Selection)& theSe
 //=======================================================================
 void AIS_Manipulator::Disk::Init (const Standard_ShortReal theInnerRadius,
                                   const Standard_ShortReal theOuterRadius,
-                                  const gp_Ax1& thePosition,
-                                  const Standard_Integer theSlicesNb,
-                                  const Standard_Integer theStacksNb)
+                                  const gp_Ax1&            thePosition,
+                                  const Standard_Real      theAngle,
+                                  const Standard_Integer   theSlicesNb,
+                                  const Standard_Integer   theStacksNb)
 {
   myPosition = thePosition;
   myInnerRad = theInnerRadius;
   myOuterRad = theOuterRadius;
 
   Prs3d_ToolDisk aTool (theInnerRadius, theOuterRadius, theSlicesNb, theStacksNb);
+  aTool.SetAngleRange (0, theAngle);
   gp_Ax3 aSystem (myPosition.Location(), myPosition.Direction());
   gp_Trsf aTrsf;
   aTrsf.SetTransformation (aSystem, gp_Ax3());
@@ -1261,15 +1516,18 @@ void AIS_Manipulator::Disk::Init (const Standard_ShortReal theInnerRadius,
 //=======================================================================
 void AIS_Manipulator::Sphere::Init (const Standard_ShortReal theRadius,
                                     const gp_Pnt& thePosition,
+                                    const ManipulatorSkin theSkinMode,
                                     const Standard_Integer theSlicesNb,
                                     const Standard_Integer theStacksNb)
 {
   myPosition = thePosition;
   myRadius = theRadius;
 
-  Prs3d_ToolSphere aTool (theRadius, theSlicesNb, theStacksNb);
   gp_Trsf aTrsf;
   aTrsf.SetTranslation (gp_Vec(gp::Origin(), thePosition));
+
+  const Standard_Real aRadius = theSkinMode == ManipulatorSkin_Flat ? theRadius * 0.5 : theRadius;
+  Prs3d_ToolSphere aTool (aRadius, theSlicesNb, theStacksNb);
   myArray = aTool.CreateTriangulation (aTrsf);
   myTriangulation = aTool.CreatePolyTriangulation (aTrsf);
 }
@@ -1279,52 +1537,75 @@ void AIS_Manipulator::Sphere::Init (const Standard_ShortReal theRadius,
 //function : Init
 //purpose  : 
 //=======================================================================
-void AIS_Manipulator::Cube::Init (const gp_Ax1& thePosition, const Standard_ShortReal theSize)
+void AIS_Manipulator::Cube::Init (const gp_Ax1& thePosition,
+                                  const Standard_ShortReal theSize,
+                                  const ManipulatorSkin theSkinMode)
 {
-  myArray = new Graphic3d_ArrayOfTriangles (12 * 3, 0, Standard_True);
-
-  Poly_Array1OfTriangle aPolyTriangles (1, 12);
-  TColgp_Array1OfPnt aPoints (1, 36);
-  NCollection_Array1<gp_Dir> aNormals (1, 12);
-  myTriangulation = new Poly_Triangulation (aPoints, aPolyTriangles);
-
-  gp_Ax2 aPln (thePosition.Location(), thePosition.Direction());
-  gp_Pnt aBottomLeft = thePosition.Location().XYZ() - aPln.XDirection().XYZ() * theSize * 0.5 - aPln.YDirection().XYZ() * theSize * 0.5;
-  gp_Pnt aV2 = aBottomLeft.XYZ() + aPln.YDirection().XYZ() * theSize;
-  gp_Pnt aV3 = aBottomLeft.XYZ() + aPln.YDirection().XYZ() * theSize + aPln.XDirection().XYZ() * theSize;
-  gp_Pnt aV4 = aBottomLeft.XYZ() + aPln.XDirection().XYZ() * theSize;
-  gp_Pnt aTopRight = thePosition.Location().XYZ() + thePosition.Direction().XYZ() * theSize
-    + aPln.XDirection().XYZ() * theSize * 0.5 + aPln.YDirection().XYZ() * theSize * 0.5;
-  gp_Pnt aV5 = aTopRight.XYZ() - aPln.YDirection().XYZ() * theSize;
-  gp_Pnt aV6 = aTopRight.XYZ() - aPln.YDirection().XYZ() * theSize - aPln.XDirection().XYZ() * theSize;
-  gp_Pnt aV7 = aTopRight.XYZ() - aPln.XDirection().XYZ() * theSize;
-
-  gp_Dir aRight ((gp_Vec(aTopRight, aV7) ^ gp_Vec(aTopRight, aV2)).XYZ());
-  gp_Dir aFront ((gp_Vec(aV3, aV4) ^ gp_Vec(aV3, aV5)).XYZ());
-
-  // Bottom
-  addTriangle (0, aBottomLeft, aV2, aV3, -thePosition.Direction());
-  addTriangle (1, aBottomLeft, aV3, aV4, -thePosition.Direction());
-
-  // Front
-  addTriangle (2, aV3, aV5, aV4, -aFront);
-  addTriangle (3, aV3, aTopRight, aV5, -aFront);
-
-  // Back
-  addTriangle (4, aBottomLeft, aV7, aV2, aFront);
-  addTriangle (5, aBottomLeft, aV6, aV7, aFront);
-
-  // aTop
-  addTriangle (6, aV7, aV6, aV5, thePosition.Direction());
-  addTriangle (7, aTopRight, aV7, aV5, thePosition.Direction());
-
-  // Left
-  addTriangle (8, aV6, aV4, aV5, aRight);
-  addTriangle (9, aBottomLeft, aV4, aV6, aRight);
-
-  // Right
-  addTriangle (10, aV3, aV7, aTopRight, -aRight);
-  addTriangle (11, aV3, aV2, aV7, -aRight);
+  if (theSkinMode == ManipulatorSkin_Flat)
+  {
+    gp_Dir aXDirection;
+    if (thePosition.Direction().X() > 0)
+      aXDirection = gp::DY();
+    else if (thePosition.Direction().Y() > 0)
+      aXDirection = gp::DZ();
+    else
+      aXDirection = gp::DX();
+
+    gp_Pnt aLocation = thePosition.Location().Translated (gp_Vec (thePosition.Direction().XYZ() * theSize));
+    gp_Ax3 aSystem (aLocation, aXDirection, thePosition.Direction());
+    gp_Trsf aTrsf;
+    aTrsf.SetTransformation (aSystem, gp_Ax3());
+
+    Prs3d_ToolDisk aTool (0.0, theSize, 40, 40);
+    myArray = aTool.CreateTriangulation (aTrsf);
+    myTriangulation = aTool.CreatePolyTriangulation (aTrsf);
+  }
+  else
+  {
+    myArray = new Graphic3d_ArrayOfTriangles (12 * 3, 0, Standard_True);
+
+    Poly_Array1OfTriangle aPolyTriangles (1, 12);
+    TColgp_Array1OfPnt aPoints (1, 36);
+    myTriangulation = new Poly_Triangulation (aPoints, aPolyTriangles);
+
+    gp_Ax2 aPln (thePosition.Location(), thePosition.Direction());
+    gp_Pnt aBottomLeft = thePosition.Location().XYZ() - aPln.XDirection().XYZ() * theSize * 0.5 - aPln.YDirection().XYZ() * theSize * 0.5;
+    gp_Pnt aV2 = aBottomLeft.XYZ() + aPln.YDirection().XYZ() * theSize;
+    gp_Pnt aV3 = aBottomLeft.XYZ() + aPln.YDirection().XYZ() * theSize + aPln.XDirection().XYZ() * theSize;
+    gp_Pnt aV4 = aBottomLeft.XYZ() + aPln.XDirection().XYZ() * theSize;
+    gp_Pnt aTopRight = thePosition.Location().XYZ() + thePosition.Direction().XYZ() * theSize
+      + aPln.XDirection().XYZ() * theSize * 0.5 + aPln.YDirection().XYZ() * theSize * 0.5;
+    gp_Pnt aV5 = aTopRight.XYZ() - aPln.YDirection().XYZ() * theSize;
+    gp_Pnt aV6 = aTopRight.XYZ() - aPln.YDirection().XYZ() * theSize - aPln.XDirection().XYZ() * theSize;
+    gp_Pnt aV7 = aTopRight.XYZ() - aPln.XDirection().XYZ() * theSize;
+
+    gp_Dir aRight ((gp_Vec(aTopRight, aV7) ^ gp_Vec(aTopRight, aV2)).XYZ());
+    gp_Dir aFront ((gp_Vec(aV3, aV4) ^ gp_Vec(aV3, aV5)).XYZ());
+
+    // Bottom
+    addTriangle (0, aBottomLeft, aV2, aV3, -thePosition.Direction());
+    addTriangle (1, aBottomLeft, aV3, aV4, -thePosition.Direction());
+
+    // Front
+    addTriangle (2, aV3, aV5, aV4, -aFront);
+    addTriangle (3, aV3, aTopRight, aV5, -aFront);
+
+    // Back
+    addTriangle (4, aBottomLeft, aV7, aV2, aFront);
+    addTriangle (5, aBottomLeft, aV6, aV7, aFront);
+
+    // aTop
+    addTriangle (6, aV7, aV6, aV5, thePosition.Direction());
+    addTriangle (7, aTopRight, aV7, aV5, thePosition.Direction());
+
+    // Left
+    addTriangle (8, aV6, aV4, aV5, aRight);
+    addTriangle (9, aBottomLeft, aV4, aV6, aRight);
+
+    // Right
+    addTriangle (10, aV3, aV7, aTopRight, -aRight);
+    addTriangle (11, aV3, aV2, aV7, -aRight);
+  }
 }
 
 //=======================================================================
@@ -1354,15 +1635,49 @@ void AIS_Manipulator::Cube::addTriangle (const Standard_Integer theIndex,
 void AIS_Manipulator::Sector::Init (const Standard_ShortReal theRadius,
                                     const gp_Ax1&            thePosition,
                                     const gp_Dir&            theXDirection,
+                                    const ManipulatorSkin    theSkinMode,
                                     const Standard_Integer   theSlicesNb,
                                     const Standard_Integer   theStacksNb)
 {
-  Prs3d_ToolSector aTool(theRadius, theSlicesNb, theStacksNb);
-  gp_Ax3 aSystem(thePosition.Location(), thePosition.Direction(), theXDirection);
+  gp_Ax3 aSystem (thePosition.Location(), thePosition.Direction(), theXDirection);
   gp_Trsf aTrsf;
-  aTrsf.SetTransformation(aSystem, gp_Ax3());
-  myArray = aTool.CreateTriangulation (aTrsf);
-  myTriangulation = aTool.CreatePolyTriangulation (aTrsf);
+  aTrsf.SetTransformation (aSystem, gp_Ax3());
+
+  if (theSkinMode == ManipulatorSkin_Flat)
+  {
+    myArray = new Graphic3d_ArrayOfTriangles (4, 6, Graphic3d_ArrayFlags_VertexNormal);
+    myTriangulation = new Poly_Triangulation (4, 2, Standard_False);
+    TColgp_Array1OfPnt& aNodes = myTriangulation->ChangeNodes();
+    Poly_Array1OfTriangle& aTriangles = myTriangulation->ChangeTriangles();
+
+    gp_Dir aNormal = gp_Dir (0.0, 0.0, -1.0).Transformed (aTrsf);
+
+    const Standard_Real anIndent = theRadius / 3.0;
+    gp_Pnt aV1 = gp_Pnt (anIndent, anIndent, 0.0).Transformed (aTrsf);
+    gp_Pnt aV2 = gp_Pnt (anIndent, anIndent * 2.0, 0.0).Transformed (aTrsf);
+    gp_Pnt aV3 = gp_Pnt (anIndent * 2.0, anIndent * 2.0, 0.0).Transformed (aTrsf);
+    gp_Pnt aV4 = gp_Pnt (anIndent * 2.0, anIndent, 0.0).Transformed (aTrsf);
+
+    myArray->AddVertex (aV1, aNormal);
+    myArray->AddVertex (aV2, aNormal);
+    myArray->AddVertex (aV3, aNormal);
+    myArray->AddVertex (aV4, aNormal);
+    myArray->AddTriangleEdges (3, 1, 2);
+    myArray->AddTriangleEdges (1, 3, 4);
+
+    aNodes.SetValue (1, aV1);
+    aNodes.SetValue (2, aV2);
+    aNodes.SetValue (3, aV3);
+    aNodes.SetValue (4, aV4);
+    aTriangles.SetValue (1, Poly_Triangle (3, 1, 2));
+    aTriangles.SetValue (2, Poly_Triangle (1, 3, 4));
+  }
+  else
+  {
+    Prs3d_ToolSector aTool(theRadius, theSlicesNb, theStacksNb);
+    myArray = aTool.CreateTriangulation (aTrsf);
+    myTriangulation = aTool.CreatePolyTriangulation (aTrsf);
+  }
 }
 
 //=======================================================================
@@ -1400,7 +1715,8 @@ AIS_Manipulator::Axis::Axis (const gp_Ax1& theAxis,
 
 void AIS_Manipulator::Axis::Compute (const Handle(PrsMgr_PresentationManager)& thePrsMgr,
                                      const Handle(Prs3d_Presentation)& thePrs,
-                                     const Handle(Prs3d_ShadingAspect)& theAspect)
+                                     const Handle(Prs3d_ShadingAspect)& theAspect,
+                                     const ManipulatorSkin theSkinMode)
 {
   if (myHasTranslation)
   {
@@ -1408,16 +1724,66 @@ void AIS_Manipulator::Axis::Compute (const Handle(PrsMgr_PresentationManager)& t
     const Standard_Real aCylinderLength = myLength - anArrowLength;
     myArrowTipPos = gp_Pnt (0.0, 0.0, 0.0).Translated (myReferenceAxis.Direction().XYZ() * aCylinderLength);
 
-    myTriangleArray = Prs3d_Arrow::DrawShaded (gp_Ax1(gp::Origin(), myReferenceAxis.Direction()),
-                                               myAxisRadius,
-                                               myLength,
-                                               myAxisRadius * 1.5,
-                                               anArrowLength,
-                                               myFacettesNumber);
     myTranslatorGroup = thePrs->NewGroup();
-    myTranslatorGroup->SetClosed (true);
+    myTranslatorGroup->SetClosed (theSkinMode == ManipulatorSkin_Shaded);
     myTranslatorGroup->SetGroupPrimitivesAspect (theAspect->Aspect());
-    myTranslatorGroup->AddPrimitiveArray (myTriangleArray);
+
+    if (theSkinMode == ManipulatorSkin_Flat)
+    {
+      const Standard_Integer aStripsNb = 14;
+
+      myTriangleArray = new Graphic3d_ArrayOfTriangles (aStripsNb * 4, aStripsNb * 6, Graphic3d_ArrayFlags_VertexNormal);
+      Handle(Graphic3d_ArrayOfTriangles) aColorlessArr = new Graphic3d_ArrayOfTriangles (aStripsNb * 2, aStripsNb * 3, Graphic3d_ArrayFlags_VertexNormal);
+      Handle(Graphic3d_ArrayOfTriangles) aColoredArr = new Graphic3d_ArrayOfTriangles (aStripsNb * 2, aStripsNb * 3,
+                                                                                       Graphic3d_ArrayFlags_VertexNormal | Graphic3d_ArrayFlags_VertexColor);
+
+      gp_Ax3  aSystem (gp::Origin(), myReferenceAxis.Direction());
+      gp_Trsf aTrsf;
+      aTrsf.SetTransformation (aSystem, gp_Ax3());
+
+      gp_Dir aNormal = gp_Dir (1.0, 0.0, 0.0).Transformed (aTrsf);
+      Standard_Real aLength = myLength + myIndent * 4.0f;
+
+      const Standard_Real aStepV = 1.0f / aStripsNb;
+      for (Standard_Integer aU = 0; aU <= 1; ++aU)
+      {
+        for (Standard_Integer aV = 0; aV <= aStripsNb; ++aV)
+        {
+          gp_Pnt aVertex = gp_Pnt (0.0, myAxisRadius * (1.5f * aU - 0.75f), aLength * aV * aStepV).Transformed (aTrsf);
+          myTriangleArray->AddVertex (aVertex, aNormal);
+
+          if (aV != 0) { aColorlessArr->AddVertex (aVertex, aNormal); }
+          if (aV != aStripsNb) { aColoredArr->AddVertex (aVertex, aNormal, myColor); }
+
+          if (aU != 0 && aV != 0)
+          {
+            int aVertId = myTriangleArray->VertexNumber();
+            myTriangleArray->AddTriangleEdges (aVertId, aVertId - aStripsNb - 2, aVertId - 1);
+            myTriangleArray->AddTriangleEdges (aVertId - aStripsNb - 2, aVertId, aVertId - aStripsNb - 1);
+
+            Handle(Graphic3d_ArrayOfTriangles) aSquares = aV % 2 == 0
+              ? aColorlessArr
+              : aColoredArr;
+
+            aVertId = aSquares->VertexNumber();
+            aSquares->AddTriangleEdges (aVertId, aVertId - aStripsNb - 1, aVertId - 1);
+            aSquares->AddTriangleEdges (aVertId - aStripsNb - 1, aVertId, aVertId - aStripsNb);
+          }
+        }
+      }
+      myTranslatorGroup->AddPrimitiveArray (aColoredArr);
+      myTranslatorGroup->AddPrimitiveArray (aColorlessArr);
+    }
+    else
+    {
+      myTriangleArray = Prs3d_Arrow::DrawShaded (gp_Ax1(gp::Origin(), myReferenceAxis.Direction()),
+                                                 myAxisRadius,
+                                                 myLength,
+                                                 myAxisRadius * 1.5,
+                                                 anArrowLength,
+                                                 myFacettesNumber);
+      myTranslatorGroup->AddPrimitiveArray (myTriangleArray);
+    }
 
     if (myHighlightTranslator.IsNull())
     {
@@ -1437,10 +1803,11 @@ void AIS_Manipulator::Axis::Compute (const Handle(PrsMgr_PresentationManager)& t
   if (myHasScaling)
   {
     myCubePos = myReferenceAxis.Direction().XYZ() * (myLength + myIndent);
-    myCube.Init (gp_Ax1 (myCubePos, myReferenceAxis.Direction()), myBoxSize);
+    const Standard_ShortReal aBoxSize = theSkinMode == ManipulatorSkin_Shaded ? myBoxSize : myBoxSize * 0.5f + myIndent;
+    myCube.Init (gp_Ax1 (myCubePos, myReferenceAxis.Direction()), aBoxSize, theSkinMode);
 
     myScalerGroup = thePrs->NewGroup();
-    myScalerGroup->SetClosed (true);
+    myScalerGroup->SetClosed (theSkinMode == ManipulatorSkin_Shaded);
     myScalerGroup->SetGroupPrimitivesAspect (theAspect->Aspect());
     myScalerGroup->AddPrimitiveArray (myCube.Array());
 
@@ -1461,8 +1828,11 @@ void AIS_Manipulator::Axis::Compute (const Handle(PrsMgr_PresentationManager)& t
 
   if (myHasRotation)
   {
-    myCircleRadius = myInnerRadius + myIndent * 2 + myDiskThickness * 0.5f;
-    myCircle.Init (myInnerRadius + myIndent * 2, myInnerRadius + myDiskThickness + myIndent * 2, gp_Ax1(gp::Origin(), myReferenceAxis.Direction()), myFacettesNumber * 2);
+    myCircleRadius = myInnerRadius + myIndent * 2.0f + myDiskThickness * 0.5f;
+    const Standard_Real anAngle = theSkinMode == ManipulatorSkin_Shaded ? M_PI * 2.0f : M_PI;
+    myCircle.Init (myInnerRadius + myIndent * 2.0f, Size(),
+                   gp_Ax1 (gp::Origin(), myReferenceAxis.Direction()),
+                   anAngle, myFacettesNumber * 2);
     myRotatorGroup = thePrs->NewGroup ();
     myRotatorGroup->SetGroupPrimitivesAspect (theAspect->Aspect());
     myRotatorGroup->AddPrimitiveArray (myCircle.Array());
@@ -1492,10 +1862,17 @@ void AIS_Manipulator::Axis::Compute (const Handle(PrsMgr_PresentationManager)& t
     else
       aXDirection = gp::DX();
 
-    mySector.Init(myInnerRadius + myIndent * 2, gp_Ax1(gp::Origin(), myReferenceAxis.Direction()), aXDirection, myFacettesNumber * 2);
+    gp_Pnt aPosition = theSkinMode == ManipulatorSkin_Flat
+      ? gp_Pnt (myReferenceAxis.Direction().Reversed().XYZ() * (myAxisRadius))
+      : gp::Origin();
+    Standard_ShortReal aRadius = theSkinMode == ManipulatorSkin_Flat ? myLength : myInnerRadius + myIndent * 2;
+    mySector.Init (aRadius, gp_Ax1 (aPosition, myReferenceAxis.Direction()), aXDirection, theSkinMode, myFacettesNumber * 2);
     myDraggerGroup = thePrs->NewGroup();
 
-    Handle(Graphic3d_AspectFillArea3d) aFillArea = new Graphic3d_AspectFillArea3d();
+    Handle(Graphic3d_AspectFillArea3d) aFillArea = theSkinMode == ManipulatorSkin_Flat
+      ? theAspect->Aspect()
+      : new Graphic3d_AspectFillArea3d();
+
     myDraggerGroup->SetGroupPrimitivesAspect(aFillArea);
     myDraggerGroup->AddPrimitiveArray(mySector.Array());
 
@@ -1509,8 +1886,8 @@ void AIS_Manipulator::Axis::Compute (const Handle(PrsMgr_PresentationManager)& t
     }
     {
       Handle(Graphic3d_Group) aGroup = myHighlightDragger->CurrentGroup();
-      aGroup->SetGroupPrimitivesAspect(aFillArea);
-      aGroup->AddPrimitiveArray(mySector.Array());
+      aGroup->SetGroupPrimitivesAspect (aFillArea);
+      aGroup->AddPrimitiveArray (mySector.Array());
     }
   }
 }
index c950e7c9aab02283ebfd08917b3750141ce40bfb..4f41747a5f7381686f4a40883fe7b37754ef7974 100644 (file)
@@ -189,6 +189,13 @@ public:
   //! @warning It will does nothing if transformation is not initiated (with StartTransform() call).
   Standard_EXPORT void Transform (const gp_Trsf& aTrsf);
 
+  //! Apply camera transformation to flat skin manipulator
+  Standard_EXPORT void RecomputeTransformation (const Handle(Graphic3d_Camera)& theCamera) Standard_OVERRIDE;
+
+  //! Recomputes sensitive primitives for the given selection mode.
+  //! @param theMode selection mode to recompute sensitive primitives
+  Standard_EXPORT void RecomputeSelection (const AIS_ManipulatorMode theMode);
+
   //! Reset start (reference) transformation.
   //! @param theToApply [in] option to apply or to cancel the started transformation.
   //! @warning It is used in chain with StartTransform-Transform(gp_Trsf)-StopTransform
@@ -268,6 +275,18 @@ public: //! @name Configuration of graphical transformations
 
 public: //! @name Setters for parameters
 
+  enum ManipulatorSkin
+  {
+    ManipulatorSkin_Shaded,
+    ManipulatorSkin_Flat
+  };
+
+  //! @return current manipulator skin mode.
+  ManipulatorSkin SkinMode() const { return mySkinMode; }
+
+  //! Sets skin mode for the manipulator.
+  Standard_EXPORT void SetSkinMode (const ManipulatorSkin theSkinMode);
+
   AIS_ManipulatorMode ActiveMode() const { return myCurrentMode; }
 
   Standard_Integer ActiveAxisIndex() const { return myCurrentIndex; }
@@ -407,9 +426,10 @@ protected: //! @name Auxiliary classes to fill presentation with proper primitiv
 
     void Init (const Standard_ShortReal theInnerRadius,
                const Standard_ShortReal theOuterRadius,
-               const gp_Ax1& thePosition,
-               const Standard_Integer theSlicesNb = 20,
-               const Standard_Integer theStacksNb = 20);
+               const gp_Ax1&            thePosition,
+               const Standard_Real      theAngle,
+               const Standard_Integer   theSlicesNb = 20,
+               const Standard_Integer   theStacksNb = 20);
 
   protected:
 
@@ -428,6 +448,7 @@ protected: //! @name Auxiliary classes to fill presentation with proper primitiv
 
     void Init (const Standard_ShortReal theRadius,
                const gp_Pnt& thePosition,
+               const ManipulatorSkin theSkinMode,
                const Standard_Integer theSlicesNb = 20,
                const Standard_Integer theStacksNb = 20);
 
@@ -444,7 +465,9 @@ protected: //! @name Auxiliary classes to fill presentation with proper primitiv
     Cube() { }
     ~Cube() { }
 
-    void Init (const gp_Ax1& thePosition, const Standard_ShortReal myBoxSize);
+    void Init (const gp_Ax1& thePosition,
+               const Standard_ShortReal myBoxSize,
+               const ManipulatorSkin theSkinMode);
 
     const Handle(Poly_Triangulation)& Triangulation() const { return myTriangulation; }
 
@@ -475,6 +498,7 @@ protected: //! @name Auxiliary classes to fill presentation with proper primitiv
     void Init(const Standard_ShortReal theRadius,
               const gp_Ax1&            thePosition,
               const gp_Dir&            theXDirection,
+              const ManipulatorSkin    theSkinMode,
               const Standard_Integer   theSlicesNb = 5,
               const Standard_Integer   theStacksNb = 5);
 
@@ -499,7 +523,8 @@ protected: //! @name Auxiliary classes to fill presentation with proper primitiv
 
     void Compute (const Handle(PrsMgr_PresentationManager)& thePrsMgr,
                   const Handle(Prs3d_Presentation)& thePrs,
-                  const Handle(Prs3d_ShadingAspect)& theAspect);
+                  const Handle(Prs3d_ShadingAspect)& theAspect,
+                  const ManipulatorSkin theSkinMode);
 
     const gp_Ax1& ReferenceAxis() const { return myReferenceAxis; }
 
@@ -573,8 +598,12 @@ protected: //! @name Auxiliary classes to fill presentation with proper primitiv
 
     Standard_ShortReal AxisLength() const { return myLength; }
 
+    Standard_ShortReal BoxSize() const { return myBoxSize; }
+
     Standard_ShortReal AxisRadius() const { return myAxisRadius; }
 
+    Standard_ShortReal Indent() const { return myIndent; }
+
     void SetAxisRadius (const Standard_ShortReal theValue) { myAxisRadius = theValue; }
 
     const Handle(Prs3d_Presentation)& TranslatorHighlightPrs() const { return myHighlightTranslator; }
@@ -599,6 +628,8 @@ protected: //! @name Auxiliary classes to fill presentation with proper primitiv
 
     Standard_ShortReal Size() const { return myLength + myBoxSize + myDiskThickness + myIndent * 2.0f; }
 
+    Standard_ShortReal InnerRadius() const { return myInnerRadius + myIndent * 2.0f; }
+
     gp_Pnt ScalerCenter (const gp_Pnt& theLocation) const { return theLocation.XYZ() + myPosition.Direction().XYZ() * (myLength + myIndent + myBoxSize * 0.5f); }
 
     void SetSize (const Standard_ShortReal theValue)
@@ -674,17 +705,23 @@ protected: //! @name Auxiliary classes to fill presentation with proper primitiv
     Handle(Prs3d_Presentation) myHighlightDragger;
 
     Handle(Graphic3d_ArrayOfTriangles) myTriangleArray;
-
   };
 
 protected:
 
-  Axis myAxes[3]; //!< Tree axes of the manipulator.
+  Axis   myAxes[3]; //!< Tree axes of the manipulator.
   Sphere myCenter; //!< Visual part displaying the center sphere of the manipulator.
   gp_Ax2 myPosition; //!< Position of the manipulator object. it displays its location and position of its axes.
 
+  Disk                    myCircle; //!< Outer circle
+  Handle(Graphic3d_Group) myCircleGroup;
+
+  Disk                    mySector; //!< Sector indicating the rotation angle
+  Handle(Graphic3d_Group) mySectorGroup;
+
   Standard_Integer myCurrentIndex; //!< Index of active axis.
   AIS_ManipulatorMode myCurrentMode; //!< Name of active manipulation mode.
+  ManipulatorSkin mySkinMode; //!< Name of active skin mode.
 
   Standard_Boolean myIsActivationOnDetection; //!< Manual activation of modes (not on parts selection).
   Standard_Boolean myIsZoomPersistentMode; //!< Zoom persistence mode activation.
index 4823afed83cb46f2013b601219fee79f220705c6..c5300149bf4df1ce9e23af9aa5aa363eaf05c193 100644 (file)
@@ -2149,6 +2149,13 @@ void AIS_ViewController::handleCameraActions (const Handle(AIS_InteractiveContex
     myGL.Orientation.ToFitAll = false;
   }
 
+  AIS_ListOfInteractive anObjects;
+  theCtx->DisplayedObjects (anObjects);
+  for (AIS_ListIteratorOfListOfInteractive anObjIter (anObjects); anObjIter.More(); anObjIter.Next())
+  {
+    anObjIter.Value()->RecomputeTransformation (theView->Camera());
+  }
+
   if (myGL.IsNewGesture)
   {
     if (myAnchorPointPrs1->HasInteractiveContext())
index 2219b947e91dfaba7b661fc943ce30a26c23fbd5..545fb202a0ce1ab609c9957995fab11bf5574e5b 100644 (file)
@@ -291,6 +291,8 @@ void Graphic3d_CView::ReCompute (const Handle(Graphic3d_Structure)& theStruct)
     return;
   }
 
+  theStruct->RecomputeTransformation (myCamera);
+
   const Graphic3d_TypeOfAnswer anAnswer = acceptDisplay (theStruct->Visual());
   if (anAnswer != Graphic3d_TOA_COMPUTE)
   {
@@ -597,6 +599,11 @@ void Graphic3d_CView::Compute()
     aStructIter.Value()->SetHLRValidation (Standard_False);
   }
 
+  for (Graphic3d_MapOfStructure::Iterator aStructIter (myStructsDisplayed); aStructIter.More(); aStructIter.Next())
+  {
+    aStructIter.Value()->RecomputeTransformation (myCamera);
+  }
+
   if (!ComputedMode())
   {
     return;
@@ -697,6 +704,8 @@ void Graphic3d_CView::Display (const Handle(Graphic3d_Structure)& theStructure)
     anIndex = 0;
   }
 
+  theStructure->RecomputeTransformation (myCamera);
+
   Graphic3d_TypeOfAnswer anAnswer = acceptDisplay (theStructure->Visual());
   if (anAnswer == Graphic3d_TOA_NO)
   {
index fb6748302edb32fa49a0635d5c12d3e911357c76..db72d688c052f39ec153ce42695004829d868456 100644 (file)
@@ -136,6 +136,12 @@ public:
   //! sets the flipping to theIsEnabled state.
   Standard_EXPORT virtual void SetFlippingOptions (const Standard_Boolean theIsEnabled, const gp_Ax2& theRefPlane) = 0;
 
+  //! Return transformation.
+  const gp_Trsf& Transformation() const { return myTrsf; }
+
+  //! Assign transformation.
+  virtual void SetTransformation (const gp_Trsf& theTrsf) { myTrsf = theTrsf; }
+
   //! Returns true if the group contains Polygons, Triangles or Quadrangles.
   bool ContainsFacet() const { return myContainsFacet; }
 
@@ -292,6 +298,7 @@ protected:
 
   Graphic3d_Structure* myStructure;     //!< pointer to the parent structure
   Graphic3d_BndBox4f   myBounds;        //!< bounding box
+  gp_Trsf              myTrsf;          //!< group transformation
   bool                 myIsClosed;      //!< flag indicating closed volume
   bool                 myContainsFacet; //!< flag indicating that this group contains face primitives
 
index 9739cbe092dd99f5f513fdd11951b3faa0df0117..aab56cc7ae545e6cf3ff985c9c13cebaac5a5d68 100644 (file)
@@ -184,6 +184,12 @@ public:
     (void )theStructure;
   }
 
+  //! Calculates structure transformation for specific camera position
+  virtual void RecomputeTransformation (const Handle(Graphic3d_Camera)& theProjector)
+  {
+    (void )theProjector;
+  }
+
   //! Forces a new construction of the structure <me>
   //! if <me> is displayed and TOS_COMPUTED.
   Standard_EXPORT void ReCompute();
index b7533c16ffd00a68b526d50e42902d85978e99c0..70e2401041a3b8e2673d898fc4b33b2e084ef44f 100644 (file)
@@ -389,10 +389,40 @@ void OpenGl_Structure::renderGeometry (const Handle(OpenGl_Workspace)& theWorksp
     myInstancedStructure->renderGeometry (theWorkspace, theHasClosed);
   }
 
+  const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
   for (OpenGl_Structure::GroupIterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
   {
+    const gp_Trsf& aTrsf = aGroupIter.Value()->Transformation();
+    applyTransformation (aCtx, aTrsf, Standard_True);
+
     theHasClosed = theHasClosed || aGroupIter.Value()->IsClosed();
     aGroupIter.Value()->Render (theWorkspace);
+
+    applyTransformation (aCtx, aTrsf, Standard_False);
+  }
+}
+
+// =======================================================================
+// function : applyTransformation
+// purpose  :
+// =======================================================================
+void OpenGl_Structure::applyTransformation (const Handle(OpenGl_Context)& theContext,
+                                            const gp_Trsf& theTrsf,
+                                            const Standard_Boolean toEnable) const
+{
+  if (toEnable)
+  {
+    OpenGl_Mat4 aTrsf;
+    theTrsf.GetMat4 (aTrsf);
+    theContext->ModelWorldState.Push();
+    OpenGl_Mat4& aModelWorld = theContext->ModelWorldState.ChangeCurrent();
+    aModelWorld = aModelWorld * aTrsf;
+    theContext->ApplyModelViewMatrix();
+  }
+  else
+  {
+    theContext->ModelWorldState.Pop();
+    theContext->ApplyModelViewMatrix();
   }
 }
 
index b031d31036fe4f7cd1b496bde525988d660c03ec..454e3080db9dddd10f5eb791bf2851c1166f1557 100644 (file)
@@ -147,6 +147,14 @@ protected:
   //! Render the bounding box.
   Standard_EXPORT void renderBoundingBox(const Handle(OpenGl_Workspace)& theWorkspace) const;
 
+  //! Apply transformation into context.
+  //! @param theWorkspace current workspace
+  //! @param theTrsf transformation
+  //! @param toEnable flag to switch ON/OFF transformation
+  Standard_EXPORT void applyTransformation (const Handle(OpenGl_Context)& theContext,
+                                            const gp_Trsf& theTrsf,
+                                            const Standard_Boolean toEnable) const;
+
 protected:
 
   OpenGl_Structure*          myInstancedStructure;
index 06c51a3065744c7fc21719d3f284814458692290..d2a20e2be61d9738028ff562840d81a2405536be 100644 (file)
@@ -255,6 +255,11 @@ public: //! @name object transformation
   //! Updates final transformation (parent + local) of presentable object and its presentations.
   Standard_EXPORT virtual void UpdateTransformation();
 
+  //! Calculates object presentation for specific camera position.
+  //! Each of the views in the viewer and every modification such as rotation, for example, entails recalculation.
+  //! @param theProjector [in] view orientation
+  virtual void RecomputeTransformation (const Handle(Graphic3d_Camera)& theProjector) { (void)theProjector; }
+
 public: //! @name clipping planes
   
   //! Get clip planes.
index c53573d46ebd7c83378f2e2fe951c5c1fa9c633e..c10c3cb622d1184e4af033b5cd6e4517857be088 100644 (file)
@@ -202,6 +202,15 @@ void PrsMgr_Presentation::computeHLR (const Handle(Graphic3d_Camera)& theProject
   myPresentableObject->computeHLR (theProjector, Transformation(), aPrs);
 }
 
+//=======================================================================
+//function : RecomputeTransformation
+//purpose  :
+//=======================================================================
+void PrsMgr_Presentation::RecomputeTransformation (const Handle(Graphic3d_Camera)& theProjector)
+{
+  myPresentableObject->RecomputeTransformation (theProjector);
+}
+
 //=======================================================================
 //function : ~PrsMgr_Presentation
 //purpose  :
index f2295b02ca9e3a976949fcd65e871c9b2e4f499d..381ddd087b8bdcb255736cad280a1513d94d3ea6 100644 (file)
@@ -94,6 +94,9 @@ protected:
 
   Standard_EXPORT virtual void computeHLR (const Handle(Graphic3d_Camera)& theProjector,
                                            Handle(Graphic3d_Structure)& theGivenStruct) Standard_OVERRIDE;
+
+  Standard_EXPORT virtual void RecomputeTransformation (const Handle(Graphic3d_Camera)& theProjector) Standard_OVERRIDE;
+
 protected:
 
   Handle(PrsMgr_PresentationManager) myPresentationManager;
index 5cb578d9389658a1613150c12dd438aabae4fe0e..1b707b727d1648f12230ae3eabb45406d1518f78 100644 (file)
@@ -12862,6 +12862,7 @@ static int VManipulator (Draw_Interpretor& theDi,
   aCmd.AddOption ("pos",               "... x y z [nx ny nz [xx xy xz]] - set position of manipulator");
   aCmd.AddOption ("size",              "... size - set size of manipulator");
   aCmd.AddOption ("zoomable",          "... {0|1} - set zoom persistence");
+  aCmd.AddOption ("flat",              "... {0|1} - set flat skin mode");
 
   aCmd.Parse (theArgsNb, theArgVec);
 
@@ -13001,6 +13002,16 @@ static int VManipulator (Draw_Interpretor& theDi,
       ViewerTest::GetAISContext()->Display (aManipulator, Standard_False);
     }
   }
+  if (aCmd.HasOption ("flat", 1, Standard_True))
+  {
+    aManipulator->SetSkinMode ((AIS_Manipulator::ManipulatorSkin) aCmd.ArgBool ("flat"));
+
+    if (ViewerTest::GetAISContext()->IsDisplayed (aManipulator))
+    {
+      ViewerTest::GetAISContext()->Remove  (aManipulator, Standard_False);
+      ViewerTest::GetAISContext()->Display (aManipulator, Standard_False);
+    }
+  }
 
   // ---------------------------------------------------
   // attach, detach or access manipulator from an object
@@ -14931,7 +14942,8 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
       "\n      '-parts axis mode   {0|1}'        - set visual part"
       "\n      '-pos x y z [nx ny nz [xx xy xz]' - set position of manipulator"
       "\n      '-size value'                     - set size of manipulator"
-      "\n      '-zoomable {0|1}'                 - set zoom persistence",
+      "\n      '-zoomable {0|1}'                 - set zoom persistence"
+      "\n      '-flat {0|1}'                     - set flat skin mode",
     __FILE__, VManipulator, group);
 
   theCommands.Add("vselprops",
diff --git a/tests/v3d/manipulator/flat b/tests/v3d/manipulator/flat
new file mode 100644 (file)
index 0000000..09bce84
--- /dev/null
@@ -0,0 +1,48 @@
+puts "==========================="
+puts "AIS_Manipulator - flat skin"
+puts "==========================="
+
+set anImage1 $imagedir/${casename}_1.png
+set anImage2 $imagedir/${casename}_2.png
+set anImage3 $imagedir/${casename}_3.png
+
+# create manipulated and helper objects
+box b 0 0 0 20 20 20
+
+# display manipulated objects
+vdisplay b -dispmode 1
+vright
+vrotate -mouseStart 400 200 -mouseMove 300 300
+vzoom 3
+
+# attach manipulator
+vmanipulator m -attach b -zoomable 1 -flat 1
+
+# test translation transform
+set mouse_pick {180 215}
+set mouse_drag {065 350}
+
+vmoveto 0 0
+vmoveto {*}$mouse_pick
+vdump $anImage1
+
+vselect {*}$mouse_pick
+vmanipulator m -startTransform {*}$mouse_pick
+vmanipulator m -transform {*}$mouse_drag
+vmanipulator m -stopTransform
+vselect 0 0
+vdump $anImage2
+
+# test plane dragging transform
+set mouse_pick {115 280}
+set mouse_drag {320 040}
+
+vmoveto 0 0
+vmoveto {*}$mouse_pick
+vdump $anImage3
+
+vselect {*}$mouse_pick
+vmanipulator m -startTransform {*}$mouse_pick
+vmanipulator m -transform {*}$mouse_drag
+vmanipulator m -stopTransform
+vselect 0 0