#include <AIS_LightSource.hxx>
#include <AIS_InteractiveContext.hxx>
+#include <gp_Quaternion.hxx>
#include <Graphic3d_ArrayOfPoints.hxx>
+#include <Graphic3d_ArrayOfPolylines.hxx>
#include <Graphic3d_ArrayOfSegments.hxx>
#include <Graphic3d_ArrayOfTriangles.hxx>
#include <Graphic3d_CView.hxx>
#include <Prs3d_ToolCylinder.hxx>
#include <Prs3d_ToolSphere.hxx>
#include <Select3D_SensitivePoint.hxx>
+#include <Select3D_SensitiveSphere.hxx>
#include <V3d_View.hxx>
IMPLEMENT_STANDARD_RTTIEXT(AIS_LightSource, AIS_InteractiveObject)
return false;
}
+//=======================================================================
+//function : HilightWithColor
+//purpose :
+//=======================================================================
+void AIS_LightSourceOwner::HilightWithColor (const Handle(PrsMgr_PresentationManager)& thePM,
+ const Handle(Prs3d_Drawer)& theStyle,
+ const Standard_Integer theMode)
+{
+ Handle(AIS_LightSource) aLightSource = Handle(AIS_LightSource)::DownCast (mySelectable);
+ if (aLightSource.IsNull())
+ {
+ return;
+ }
+
+ if (aLightSource->Light()->Type() == Graphic3d_TypeOfLightSource_Directional && aLightSource->myIsDraggable)
+ {
+ Handle(Prs3d_Presentation) aPrs = aLightSource->GetHilightPresentation (thePM);
+ const Graphic3d_ZLayerId aZLayer = theStyle->ZLayer() != -1
+ ? theStyle->ZLayer()
+ : (thePM->IsImmediateModeOn() ? Graphic3d_ZLayerId_Top : aLightSource->ZLayer());
+ aPrs->Clear();
+ if (aPrs->GetZLayer() != aZLayer)
+ {
+ aPrs->SetZLayer (aZLayer);
+ }
+ Handle(Graphic3d_ArrayOfPoints) aPoints = new Graphic3d_ArrayOfPoints (1);
+ const gp_Pnt aDetPnt = aLightSource->mySensSphere->LastDetectedPoint();
+ if (aDetPnt.X() == RealLast())
+ {
+ return;
+ }
+ aPoints->AddVertex (aDetPnt);
+ Handle(Graphic3d_Group) aGroup = aPrs->NewGroup();
+ const Handle(Prs3d_PointAspect) aPointAspect = new Prs3d_PointAspect (Aspect_TOM_O_POINT, theStyle->Color(), 3.0f);
+ aGroup->SetGroupPrimitivesAspect (aPointAspect->Aspect());
+ aGroup->AddPrimitiveArray (aPoints);
+
+ const Standard_Real aRadius = aLightSource->Size() * 0.5;
+ const Standard_Integer aNbPnts = int (aLightSource->ArcSize() * 180 / (M_PI * aRadius));
+ TColgp_Array1OfPnt aCircPoints (0, aNbPnts);
+ const gp_Dir aDirNorm (gp_Vec (gp::Origin(), aDetPnt));
+ gp_Dir aDirNormToPln (gp::DY());
+ if (!gp::DX().IsParallel (aDirNorm, Precision::Angular()))
+ {
+ aDirNormToPln = gp::DX().Crossed (aDirNorm);
+ }
+ for (Standard_Integer aStep = 0; aStep < aNbPnts; ++aStep)
+ {
+ aCircPoints.SetValue (aStep, (aDetPnt.Rotated (gp_Ax1 (gp::Origin(), aDirNormToPln), M_PI / 90 * (aStep - aNbPnts / 2))));
+ }
+
+ Handle(Graphic3d_Group) aCircGroup = aPrs->NewGroup();
+ Handle(Graphic3d_ArrayOfPolylines) aPolylines = new Graphic3d_ArrayOfPolylines (aNbPnts * 2, 2);
+ aPolylines->AddBound (aNbPnts);
+
+ for (Standard_Integer anIdx = 0; anIdx < aNbPnts; ++anIdx)
+ {
+ aPolylines->AddVertex (aCircPoints.Value (anIdx).Rotated (gp_Ax1 (gp::Origin(), aDirNorm), M_PI / 2));
+ }
+ aPolylines->AddBound (aNbPnts);
+ for (Standard_Integer anIdx = 0; anIdx < aNbPnts; ++anIdx)
+ {
+ aPolylines->AddVertex (aCircPoints.Value (anIdx));
+ }
+ aCircGroup->AddPrimitiveArray (aPolylines, Standard_False);
+ aCircGroup->SetGroupPrimitivesAspect (theStyle->ArrowAspect()->Aspect());
+ if (thePM->IsImmediateModeOn())
+ {
+ thePM->AddToImmediateList (aPrs);
+ }
+ else
+ {
+ aPrs->Display();
+ }
+ }
+ else
+ {
+ base_type::HilightWithColor (thePM, theStyle, theMode);;
+ }
+}
+
+//=======================================================================
+//function : IsForcedHilight
+//purpose :
+//=======================================================================
+Standard_Boolean AIS_LightSourceOwner::IsForcedHilight() const
+{
+ Handle(AIS_LightSource) aLightSource = Handle(AIS_LightSource)::DownCast (mySelectable);
+ if (aLightSource.IsNull())
+ {
+ return Standard_False;
+ }
+ if (aLightSource->Light()->Type() == Graphic3d_TypeOfLightSource_Directional)
+ {
+ return Standard_True;
+ }
+ return Standard_False;
+}
+
// =======================================================================
// function : Constructor
// purpose :
myNbArrows (5),
myNbSplitsQuadric (theLight->Type() == Graphic3d_TypeOfLightSource_Ambient ? 10 : 30),
myNbSplitsArrow (20),
+ mySensSphereArcSize (25),
myIsZoomable (theLight->Type() == Graphic3d_TypeOfLightSource_Positional
|| theLight->Type() == Graphic3d_TypeOfLightSource_Spot),
+ myIsDraggable (theLight->Type() == Graphic3d_TypeOfLightSource_Directional),
myToDisplayName (true),
myToDisplayRange (true),
myToSwitchOnClick (true)
}
}
+//=======================================================================
+//function : ProcessDragging
+//purpose :
+//=======================================================================
+Standard_Boolean AIS_LightSource::ProcessDragging (const Handle(AIS_InteractiveContext)& theCtx,
+ const Handle(V3d_View)& theView,
+ const Handle(SelectMgr_EntityOwner)& theOwner,
+ const Graphic3d_Vec2i& theDragFrom,
+ const Graphic3d_Vec2i& theDragTo,
+ const AIS_DragAction theAction)
+{
+ if (Light()->Type() != Graphic3d_TypeOfLightSource_Directional)
+ {
+ return Standard_False;
+ }
+
+ switch (theAction)
+ {
+ case AIS_DragAction_Start:
+ {
+ myStartTransform = theDragFrom;
+ myLocTrsfStart = LocalTransformation();
+ return Standard_True;
+ }
+ case AIS_DragAction_Update:
+ {
+ theCtx->MainSelector()->Pick (myStartTransform.x(), myStartTransform.y(), theView);
+ gp_Pnt aStartPosition = mySensSphere->LastDetectedPoint();
+ theCtx->MainSelector()->Pick (theDragTo.x(), theDragTo.y(), theView);
+ gp_Pnt aCurrPosition = mySensSphere->LastDetectedPoint();
+ if (aCurrPosition.X() != RealLast() && aStartPosition.Distance (aCurrPosition) > Precision::Confusion())
+ {
+ gp_Quaternion aQRot;
+ aQRot.SetRotation (gp_Vec (gp_Pnt (0, 0, 0), aStartPosition), gp_Vec (gp_Pnt (0, 0, 0), aCurrPosition));
+ gp_Trsf aTrsf;
+ aTrsf.SetRotation (aQRot);
+ SetLocalTransformation (myLocTrsfStart * aTrsf);
+ myLocTrsfStart = LocalTransformation();
+ myStartTransform = theDragTo;
+ theOwner->Selectable()->ClearDynamicHighlight (theCtx->MainPrsMgr());
+ theCtx->HilightWithColor (this, Handle(Prs3d_Drawer)(), false);
+ }
+ return Standard_True;
+ }
+ case AIS_DragAction_Abort:
+ {
+ return Standard_True;
+ }
+ case AIS_DragAction_Stop:
+ {
+ GetHilightPresentation (theCtx->MainPrsMgr())->Clear();
+ break;
+ }
+ }
+ return Standard_False;
+}
+
// =======================================================================
// function : updateLightAspects
// purpose :
Handle(AIS_LightSourceOwner) anEntityOwner = new AIS_LightSourceOwner (this, 15);
{
+ if (myLightSource->Type() == Graphic3d_TypeOfLightSource_Directional)
+ {
+ mySensSphere = new Select3D_SensitiveSphere (anEntityOwner, gp::Origin(), mySize * 0.5);
+ theSel->Add (mySensSphere);
+ }
+
Handle(Select3D_SensitivePoint) aSensPosition = new Select3D_SensitivePoint (anEntityOwner, gp::Origin());
aSensPosition->SetSensitivityFactor (12);
if (!myTransformPersistence.IsNull()
#include <SelectMgr_EntityOwner.hxx>
class Prs3d_ShadingAspect;
+class Select3D_SensitiveSphere;
//! Interactive object for a light source.
//! Each type of light source has it's own presentation:
}
}
+ //! Returns Sensitive sphere arc size in pixels; 20 by default.
+ Standard_Integer ArcSize() const { return mySensSphereArcSize; }
+
+ //! Sets the size of sensitive sphere arc.
+ void SetArcSize (Standard_Integer theSize)
+ {
+ if (mySensSphereArcSize != theSize)
+ {
+ mySensSphereArcSize = theSize;
+ SetToUpdate();
+ }
+ }
+
//! Returns TRUE if transform-persistence is allowed;
//! TRUE by default for Ambient and Directional lights
//! and FALSE by default for Positional and Spot lights.
}
}
+ //! Sets if dragging is allowed.
+ void SetDraggable (bool theIsDraggable)
+ {
+ if (myIsDraggable != theIsDraggable)
+ {
+ myIsDraggable = theIsDraggable;
+ }
+ }
+
//! Returns TRUE if mouse click will turn light on/off; TRUE by default.
bool ToSwitchOnClick() const { return myToSwitchOnClick; }
Standard_EXPORT virtual void ComputeSelection (const Handle(SelectMgr_Selection)& theSel,
const Standard_Integer theMode) Standard_OVERRIDE;
+ //! Drag object in the viewer.
+ //! @param[in] theCtx interactive context
+ //! @param[in] theView active View
+ //! @param[in] theOwner the owner of detected entity
+ //! @param[in] theDragFrom drag start point
+ //! @param[in] theDragTo drag end point
+ //! @param[in] theAction drag action
+ //! @return FALSE if object rejects dragging action (e.g. AIS_DragAction_Start)
+ Standard_EXPORT virtual Standard_Boolean ProcessDragging (const Handle(AIS_InteractiveContext)& theCtx,
+ const Handle(V3d_View)& theView,
+ const Handle(SelectMgr_EntityOwner)& theOwner,
+ const Graphic3d_Vec2i& theDragFrom,
+ const Graphic3d_Vec2i& theDragTo,
+ const AIS_DragAction theAction) Standard_OVERRIDE;
+
//! Sets new local transformation, which is propagated to Graphic3d_CLight instance.
Standard_EXPORT virtual void setLocalTransformation (const Handle(TopLoc_Datum3D)& theTrsf) Standard_OVERRIDE;
Handle(Graphic3d_AspectMarker3d) myDisabledMarkerAspect; //!< disabled light source marker style
Handle(Graphic3d_AspectLine3d) myArrowLineAspectShadow; //!< arrow shadow style
Handle(Graphic3d_MarkerImage) myMarkerImages[2]; //!< icon of disabled (0) and enabled (1) light
+ Handle(Select3D_SensitiveSphere) mySensSphere; //!< sensitive sphere of directional light source
Aspect_TypeOfMarker myMarkerTypes[2]; //!< icon of disabled (0) and enabled (1) light
Aspect_TypeOfMarker myCodirMarkerType; //!< icon of arrow co-directional to camera direction (look from)
Aspect_TypeOfMarker myOpposMarkerType; //!< icon of arrow opposite to camera direction (look at)
- Standard_Real mySize; //!< presentation size
- Standard_Integer myNbArrows; //!< number of directional light arrows
- Standard_Integer myNbSplitsQuadric; //!< tessellation level for quadric surfaces
- Standard_Integer myNbSplitsArrow; //!< tessellation level for arrows
- Standard_Boolean myIsZoomable; //!< flag to allow/disallow transform-persistence when possible
- Standard_Boolean myToDisplayName; //!< flag to show/hide name
- Standard_Boolean myToDisplayRange; //!< flag to show/hide range of positional/spot light
- Standard_Boolean myToSwitchOnClick; //!< flag to handle mouse click to turn light on/off
+ Graphic3d_Vec2i myStartTransform; //!< position of starting transformation
+ gp_Trsf myLocTrsfStart; //!< object transformation before transformation
+ Standard_Real mySize; //!< presentation size
+ Standard_Integer myNbArrows; //!< number of directional light arrows
+ Standard_Integer myNbSplitsQuadric; //!< tessellation level for quadric surfaces
+ Standard_Integer myNbSplitsArrow; //!< tessellation level for arrows
+ Standard_Integer mySensSphereArcSize; //! sensitive sphere arc size in pixels
+ Standard_Boolean myIsZoomable; //!< flag to allow/disallow transform-persistence when possible
+ Standard_Boolean myIsDraggable; //!< flag to allow/disallow rotate directional light source by dragging
+ Standard_Boolean myToDisplayName; //!< flag to show/hide name
+ Standard_Boolean myToDisplayRange; //!< flag to show/hide range of positional/spot light
+ Standard_Boolean myToSwitchOnClick; //!< flag to handle mouse click to turn light on/off
};
Aspect_VKeyFlags theModifiers,
bool theIsDoubleClick) Standard_OVERRIDE;
+ //! Highlights selectable object's presentation with display mode in presentation manager with given highlight style.
+ //! Also a check for auto-highlight is performed - if selectable object manages highlighting on its own,
+ //! execution will be passed to SelectMgr_SelectableObject::HilightOwnerWithColor method.
+ Standard_EXPORT virtual void HilightWithColor (const Handle(PrsMgr_PresentationManager)& thePrsMgr,
+ const Handle(Prs3d_Drawer)& theStyle,
+ const Standard_Integer theMode) Standard_OVERRIDE;
+
+ //! Always update dynamic highlighting.
+ Standard_EXPORT virtual Standard_Boolean IsForcedHilight() const Standard_OVERRIDE;
+
};
#endif // _AIS_LightSource_HeaderFile
const Standard_Real theRadius)
: Select3D_SensitiveEntity (theOwnerId),
myCenter (theCenter),
+ myLastDetectedPoint (RealLast(), RealLast(), RealLast()),
myRadius (theRadius)
{
}
Standard_Boolean Select3D_SensitiveSphere::Matches (SelectBasics_SelectingVolumeManager& theMgr,
SelectBasics_PickResult& thePickResult)
{
+ myLastDetectedPoint = gp_Pnt (RealLast(), RealLast(), RealLast());
if (theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Point)
{
if (!theMgr.IsOverlapAllowed())
{
return Standard_False;
}
-
+ myLastDetectedPoint = thePickResult.PickedPoint();
thePickResult.SetDistToGeomCenter (theMgr.DistToGeometryCenter (myCenter));
return Standard_True;
}
//! Returns center of the sphere with transformation applied
virtual gp_Pnt CenterOfGeometry() const Standard_OVERRIDE { return myCenter; };
+ //! Returns the position of detected point on the sphere.
+ const gp_Pnt& LastDetectedPoint() const { return myLastDetectedPoint; }
+
protected:
gp_Pnt myCenter;
+ gp_Pnt myLastDetectedPoint;
Standard_Real myRadius;
};
{
Standard_ASSERT_RAISE (mySelectionType == SelectMgr_SelectionType_Point || mySelectionType == SelectMgr_SelectionType_Box,
"Error! SelectMgr_RectangularFrustum::Overlaps() should be called after selection frustum initialization");
- if (!hasSphereOverlap (theCenter, theRadius))
- {
- return Standard_False;
- }
-
Standard_Real aTimeEnter = 0.0, aTimeLeave = 0.0;
if (!RaySphereIntersection (theCenter, theRadius, myNearPickedPnt, myViewRayDir, aTimeEnter, aTimeLeave))
{
{
thePickResult.SetDepth (aTimeLeave * myScale);
}
- gp_Pnt aPntOnSphere (myNearPickedPnt.XYZ() + myViewRayDir.XYZ() * thePickResult.Depth());
+ gp_Pnt aPntOnSphere (myNearPickedPnt.XYZ() + myViewRayDir.XYZ() * thePickResult.Depth() / myScale);
gp_Vec aNormal (aPntOnSphere.XYZ() - theCenter.XYZ());
thePickResult.SetPickedPoint (aPntOnSphere);
thePickResult.SetSurfaceNormal (aNormal);
const bool isZoomable = Draw::ParseOnOffIterator (theArgsNb, theArgVec, anArgIt);
aLightPrs->SetZoomable (isZoomable);
}
+ else if (!aLightPrs.IsNull()
+ && (anArgCase == "-showdraggable"
+ || anArgCase == "-prsdraggable"
+ || anArgCase == "-draggable"))
+ {
+ const bool isDraggable = Draw::ParseOnOffIterator (theArgsNb, theArgVec, anArgIt);
+ aLightPrs->SetDraggable (isDraggable);
+ }
else if (!aLightPrs.IsNull()
&& (anArgCase == "-showname"
|| anArgCase == "-prsname"))
aLightPrs->SetSize (aSize);
}
+ else if (!aLightPrs.IsNull()
+ && (anArgCase == "-dirarcsize"
+ || anArgCase == "-arcsize"
+ || anArgCase == "-arc")
+ && anArgIt + 1 < theArgsNb)
+ {
+ Standard_Integer aSize = 0;
+ if (!Draw::ParseInteger (theArgVec[anArgIt + 1], aSize)
+ || aSize <= 0
+ || aLightPrs->Light()->Type() != Graphic3d_TypeOfLightSource_Directional)
+ {
+ Message::SendFail() << "Syntax error at argument '" << anArg << "'";
+ return 1;
+ }
+ ++anArgIt;
+ aLightPrs->SetArcSize (aSize);
+ }
else if (!aLightNew.IsNull()
&& aLightNew->Type() != Graphic3d_TypeOfLightSource_Ambient
&& (anArgCase == "-castshadow"
"\n\t\t: [-spotExponent value] [-spotAngle angleDeg]"
"\n\t\t: [-smoothAngle value] [-smoothRadius value]"
"\n\t\t: [-display] [-showName 1|0] [-showRange 1|0] [-prsZoomable 1|0] [-prsSize Value]"
+ "\n\t\t: [-arcSize Value]"
"\n\t\t: Command manages light sources. Without arguments shows list of lights."
"\n\t\t: Arguments affecting the list of defined/active lights:"
"\n\t\t: -clear remove all light sources"
"\n\t\t: -showName shows/hides the name of light source; 1 by default"
"\n\t\t: -showRange shows/hides the range of spot/positional light source; 1 by default"
"\n\t\t: -prsZoomable makes light presentation zoomable/non-zoomable"
+ "\n\t\t: -prsDraggable makes light presentation draggable/non-draggable"
"\n\t\t: -prsSize sets light presentation size"
+ "\n\t\t: -arcSize sets arc presentation size(in pixels) for rotation directional light source; 25 by default"
"\n\t\t: Examples:"
"\n\t\t: vlight redlight -type POSITIONAL -headlight 1 -pos 0 1 1 -color RED"
"\n\t\t: vlight redlight -delete",
--- /dev/null
+puts "================================="
+puts "0032183: Visualization - implement AIS_LightSource::ProcessDragging() for rotating directional light"
+puts "Tests dynamic highlighting of directional light source"
+puts "================================="
+
+pload MODELING VISUALIZATION
+vclear
+vinit View1 -height 480 -width 640
+vlight -clear
+vbackground -color GRAY
+vrenderparams -shadingModel PHONG
+box b 10 10 10 10 10 10
+vdisplay b -dispMode 1
+vaspects b -material Brass
+vfit
+
+vlight -add ambient -color WHITE -name AMBIENT -display
+vlight -add directional -dir 1 0 0 -name DIR1 -color BLUE -display
+vlight -add directional -dir 0 1 0 -name DIR2 -color RED -display -prsSize 200 -arcsize 50
+
+vmoveto 350 202
+vdump $imagedir/${casename}_dyn_highlighting_red_light_draggable.png
+if { ![string match "*Select3D_SensitiveSphere*" [vstate -entities]] } { puts "Error: sphere should be detected" }
+vmoveto 354 101
+if { ![string match "*Select3D_SensitiveSphere*" [vstate -entities]] } { puts "Error: sphere should be detected" }
+vmoveto 445 169
+if { ![string match "*Select3D_SensitiveSphere*" [vstate -entities]] } { puts "Error: sphere should be detected" }
+vmoveto 259 239
+if { ![string match "*Select3D_SensitiveSphere*" [vstate -entities]] } { puts "Error: sphere should be detected" }
+
+vmoveto 122 50
+vdump $imagedir/${casename}_dyn_highlighting_blue_light_draggable.png
+if { ![string match "*Select3D_SensitiveSphere*" [vstate -entities]] } { puts "Error: sphere should be detected" }
+vmoveto 126 25
+if { ![string match "*Select3D_SensitiveSphere*" [vstate -entities]] } { puts "Error: sphere should be detected" }
+vmoveto 149 46
+if { ![string match "*Select3D_SensitiveSphere*" [vstate -entities]] } { puts "Error: sphere should be detected" }
+vmoveto 101 47
+if { ![string match "*Select3D_SensitiveSphere*" [vstate -entities]] } { puts "Error: sphere should be detected" }
+
+vlight -change 2 -prsDraggable 0
+vmoveto 350 202
+vdump $imagedir/${casename}_dyn_highlighting_red_light_non_draggable.png
+vlight -change 1 -prsDraggable 0
+vmoveto 122 50
+vdump $imagedir/${casename}_dyn_highlighting_blue_light_non_draggable.png
\ No newline at end of file