From 3fb7f6481652d3b3be15ab9972f979fabf75f232 Mon Sep 17 00:00:00 2001 From: mzernova Date: Fri, 25 Sep 2020 17:53:09 +0300 Subject: [PATCH] 0031644: Visualization - flat skin for AIS_Manipulator presentation 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 --- src/AIS/AIS_InteractiveContext.cxx | 6 + src/AIS/AIS_Manipulator.cxx | 635 +++++++++++++++---- src/AIS/AIS_Manipulator.hxx | 51 +- src/AIS/AIS_ViewController.cxx | 7 + src/Graphic3d/Graphic3d_CView.cxx | 9 + src/Graphic3d/Graphic3d_Group.hxx | 7 + src/Graphic3d/Graphic3d_Structure.hxx | 6 + src/OpenGl/OpenGl_Structure.cxx | 30 + src/OpenGl/OpenGl_Structure.hxx | 8 + src/PrsMgr/PrsMgr_PresentableObject.hxx | 5 + src/PrsMgr/PrsMgr_Presentation.cxx | 9 + src/PrsMgr/PrsMgr_Presentation.hxx | 3 + src/ViewerTest/ViewerTest_ViewerCommands.cxx | 14 +- tests/v3d/manipulator/flat | 48 ++ 14 files changed, 701 insertions(+), 137 deletions(-) create mode 100644 tests/v3d/manipulator/flat diff --git a/src/AIS/AIS_InteractiveContext.cxx b/src/AIS/AIS_InteractiveContext.cxx index 67fece1c1f..a3cbfd3e31 100644 --- a/src/AIS/AIS_InteractiveContext.cxx +++ b/src/AIS/AIS_InteractiveContext.cxx @@ -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 : diff --git a/src/AIS/AIS_Manipulator.cxx b/src/AIS/AIS_Manipulator.cxx index 53d75ed000..6436db0dd3 100644 --- a/src/AIS/AIS_Manipulator.cxx +++ b/src/AIS/AIS_Manipulator.cxx @@ -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 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()); } } } diff --git a/src/AIS/AIS_Manipulator.hxx b/src/AIS/AIS_Manipulator.hxx index c950e7c9aa..4f41747a5f 100644 --- a/src/AIS/AIS_Manipulator.hxx +++ b/src/AIS/AIS_Manipulator.hxx @@ -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. diff --git a/src/AIS/AIS_ViewController.cxx b/src/AIS/AIS_ViewController.cxx index 4823afed83..c5300149bf 100644 --- a/src/AIS/AIS_ViewController.cxx +++ b/src/AIS/AIS_ViewController.cxx @@ -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()) diff --git a/src/Graphic3d/Graphic3d_CView.cxx b/src/Graphic3d/Graphic3d_CView.cxx index 2219b947e9..545fb202a0 100644 --- a/src/Graphic3d/Graphic3d_CView.cxx +++ b/src/Graphic3d/Graphic3d_CView.cxx @@ -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) { diff --git a/src/Graphic3d/Graphic3d_Group.hxx b/src/Graphic3d/Graphic3d_Group.hxx index fb6748302e..db72d688c0 100644 --- a/src/Graphic3d/Graphic3d_Group.hxx +++ b/src/Graphic3d/Graphic3d_Group.hxx @@ -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 diff --git a/src/Graphic3d/Graphic3d_Structure.hxx b/src/Graphic3d/Graphic3d_Structure.hxx index 9739cbe092..aab56cc7ae 100644 --- a/src/Graphic3d/Graphic3d_Structure.hxx +++ b/src/Graphic3d/Graphic3d_Structure.hxx @@ -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 //! if is displayed and TOS_COMPUTED. Standard_EXPORT void ReCompute(); diff --git a/src/OpenGl/OpenGl_Structure.cxx b/src/OpenGl/OpenGl_Structure.cxx index b7533c16ff..70e2401041 100644 --- a/src/OpenGl/OpenGl_Structure.cxx +++ b/src/OpenGl/OpenGl_Structure.cxx @@ -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(); } } diff --git a/src/OpenGl/OpenGl_Structure.hxx b/src/OpenGl/OpenGl_Structure.hxx index b031d31036..454e3080db 100644 --- a/src/OpenGl/OpenGl_Structure.hxx +++ b/src/OpenGl/OpenGl_Structure.hxx @@ -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; diff --git a/src/PrsMgr/PrsMgr_PresentableObject.hxx b/src/PrsMgr/PrsMgr_PresentableObject.hxx index 06c51a3065..d2a20e2be6 100644 --- a/src/PrsMgr/PrsMgr_PresentableObject.hxx +++ b/src/PrsMgr/PrsMgr_PresentableObject.hxx @@ -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. diff --git a/src/PrsMgr/PrsMgr_Presentation.cxx b/src/PrsMgr/PrsMgr_Presentation.cxx index c53573d46e..c10c3cb622 100644 --- a/src/PrsMgr/PrsMgr_Presentation.cxx +++ b/src/PrsMgr/PrsMgr_Presentation.cxx @@ -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 : diff --git a/src/PrsMgr/PrsMgr_Presentation.hxx b/src/PrsMgr/PrsMgr_Presentation.hxx index f2295b02ca..381ddd087b 100644 --- a/src/PrsMgr/PrsMgr_Presentation.hxx +++ b/src/PrsMgr/PrsMgr_Presentation.hxx @@ -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; diff --git a/src/ViewerTest/ViewerTest_ViewerCommands.cxx b/src/ViewerTest/ViewerTest_ViewerCommands.cxx index 5cb578d938..1b707b727d 100644 --- a/src/ViewerTest/ViewerTest_ViewerCommands.cxx +++ b/src/ViewerTest/ViewerTest_ViewerCommands.cxx @@ -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 index 0000000000..09bce84794 --- /dev/null +++ b/tests/v3d/manipulator/flat @@ -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 -- 2.39.5