Added new class AIS_LightSource representing a light source presentation.
Graphic3d_TMF_CameraPers - added new mode to Graphic3d_TransformPers
defining 3D point relative to camera Eye position
AIS_KindOfInteractive_Object, //!< presentation of group of topological shapes
AIS_KindOfInteractive_Relation, //!< presentation of relation (dimensions and constraints)
AIS_KindOfInteractive_Dimension, //!< presentation of dimension (length, radius, diameter and angle)
+ AIS_KindOfInteractive_LightSource, //!< presentation of light source
// old aliases
AIS_KOI_None = AIS_KindOfInteractive_None,
--- /dev/null
+// Created on: 2020-09-07
+// Created by: Maria KRYLOVA
+// Copyright (c) 2020 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <AIS_LightSource.hxx>
+
+#include <AIS_InteractiveContext.hxx>
+#include <Graphic3d_ArrayOfPoints.hxx>
+#include <Graphic3d_ArrayOfSegments.hxx>
+#include <Graphic3d_ArrayOfTriangles.hxx>
+#include <Graphic3d_CView.hxx>
+#include <Graphic3d_Group.hxx>
+#include <Prs3d_ArrowAspect.hxx>
+#include <Prs3d_PointAspect.hxx>
+#include <Prs3d_Text.hxx>
+#include <Prs3d_ToolCylinder.hxx>
+#include <Prs3d_ToolSphere.hxx>
+#include <Select3D_SensitivePoint.hxx>
+#include <V3d_View.hxx>
+
+IMPLEMENT_STANDARD_RTTIEXT(AIS_LightSource, AIS_InteractiveObject)
+IMPLEMENT_STANDARD_RTTIEXT(AIS_LightSourceOwner, SelectMgr_EntityOwner)
+
+// =======================================================================
+// function : AIS_LightSourceOwner
+// purpose :
+// =======================================================================
+AIS_LightSourceOwner::AIS_LightSourceOwner (const Handle(AIS_LightSource)& theObject,
+ Standard_Integer thePriority)
+: SelectMgr_EntityOwner ((const Handle(SelectMgr_SelectableObject)&)theObject, thePriority)
+{
+ //
+}
+
+// =======================================================================
+// function : HandleMouseClick
+// purpose :
+// =======================================================================
+Standard_Boolean AIS_LightSourceOwner::HandleMouseClick (const Graphic3d_Vec2i& ,
+ Aspect_VKeyMouse theKey,
+ Aspect_VKeyFlags theFlags,
+ bool )
+{
+ AIS_LightSource* aLightSource = dynamic_cast<AIS_LightSource*>(mySelectable);
+ if (aLightSource != NULL
+ && aLightSource->ToSwitchOnClick()
+ && theKey == Aspect_VKeyMouse_LeftButton
+ && theFlags == Aspect_VKeyFlags_NONE)
+ {
+ aLightSource->Light()->SetEnabled (!aLightSource->Light()->IsEnabled());
+ aLightSource->updateLightAspects();
+ return true;
+ }
+ return false;
+}
+
+// =======================================================================
+// function : Constructor
+// purpose :
+// =======================================================================
+AIS_LightSource::AIS_LightSource (const Handle(Graphic3d_CLight)& theLight)
+: myLightSource (theLight),
+ myCodirMarkerType (Aspect_TOM_X),
+ myOpposMarkerType (Aspect_TOM_O_POINT),
+ mySize (50),
+ myNbArrows (5),
+ myNbSplitsQuadric (theLight->Type() == Graphic3d_TOLS_AMBIENT ? 10 : 30),
+ myNbSplitsArrow (20),
+ myIsZoomable (theLight->Type() == Graphic3d_TOLS_POSITIONAL
+ || theLight->Type() == Graphic3d_TOLS_SPOT),
+ myToDisplayName (true),
+ myToDisplayRange (true),
+ myToSwitchOnClick (true)
+{
+ myMarkerTypes[0] = Aspect_TOM_O_X;
+ myMarkerTypes[1] = Aspect_TOM_O_POINT;
+
+ myInfiniteState = true;
+
+ const Quantity_Color aColor = theLight->Color();
+ myDrawer->SetPointAspect (new Prs3d_PointAspect (myMarkerTypes[1], aColor, 3.0f));
+ myDisabledMarkerAspect = new Graphic3d_AspectMarker3d (Aspect_TOM_EMPTY, aColor, 3.0f);
+
+ Graphic3d_MaterialAspect aMat (Graphic3d_NameOfMaterial_UserDefined);
+ aMat.SetColor (aColor);
+ myDrawer->SetArrowAspect (new Prs3d_ArrowAspect());
+ myDrawer->ArrowAspect()->SetColor (aColor);
+ myDrawer->ArrowAspect()->Aspect()->SetShadingModel (Graphic3d_TOSM_UNLIT);
+ myDrawer->ArrowAspect()->Aspect()->ChangeFrontMaterial() = aMat;
+ myDrawer->ArrowAspect()->Aspect()->SetMarkerType (Aspect_TOM_EMPTY);
+ myDrawer->ArrowAspect()->Aspect()->SetMarkerScale (2.0f);
+ myArrowLineAspectShadow = new Graphic3d_AspectLine3d (Quantity_NOC_BLACK, Aspect_TOL_SOLID,
+ theLight->Type() != Graphic3d_TOLS_AMBIENT ? 3.0f : 1.0f);
+
+ myDrawer->SetupOwnShadingAspect();
+ myDrawer->ShadingAspect()->SetColor (aColor);
+ myDrawer->ShadingAspect()->SetMaterial (aMat);
+ myDrawer->ShadingAspect()->SetTransparency (0.5f);
+ myDrawer->ShadingAspect()->Aspect()->SetShadingModel (Graphic3d_TOSM_UNLIT);
+
+ myDrawer->SetTextAspect (new Prs3d_TextAspect());
+ myDrawer->TextAspect()->Aspect()->SetDisplayType (Aspect_TODT_SHADOW);
+ myDrawer->TextAspect()->Aspect()->SetColorSubTitle (Quantity_NOC_BLACK);
+ myDrawer->TextAspect()->SetHorizontalJustification (Graphic3d_HTA_LEFT);
+ myDrawer->TextAspect()->SetVerticalJustification (Graphic3d_VTA_TOPFIRSTLINE);
+
+ updateLightTransformPersistence();
+
+ myDrawer->SetDisplayMode (0);
+ myDynHilightDrawer = new Prs3d_Drawer();
+ myDynHilightDrawer->Link (myDrawer);
+ myDynHilightDrawer->SetDisplayMode (1);
+ myDynHilightDrawer->SetColor (Quantity_NOC_CYAN1);
+
+ if (!myTransformPersistence.IsNull()
+ && myTransformPersistence->IsTrihedronOr2d())
+ {
+ myDrawer->SetZLayer (Graphic3d_ZLayerId_Topmost);
+ myDynHilightDrawer->SetZLayer (Graphic3d_ZLayerId_Topmost);
+ myDrawer->TextAspect()->SetHorizontalJustification (Graphic3d_HTA_CENTER);
+ myDrawer->TextAspect()->SetVerticalJustification (Graphic3d_VTA_TOP);
+ }
+}
+
+// =======================================================================
+// function : updateLightAspects
+// purpose :
+// =======================================================================
+void AIS_LightSource::updateLightAspects()
+{
+ const Quantity_Color aBaseColor = myLightSource->Color();
+ const Quantity_Color aDimColor (aBaseColor.Rgb() * 0.3f);
+ const Quantity_Color aColor = myLightSource->IsEnabled() ? aBaseColor : aDimColor;
+ myDrawer->PointAspect()->SetColor (aColor);
+ myDrawer->PointAspect()->Aspect()->SetMarkerType (MarkerType (myLightSource->IsEnabled()));
+ myDrawer->PointAspect()->Aspect()->SetMarkerImage(MarkerImage(myLightSource->IsEnabled()));
+
+ myDisabledMarkerAspect->SetColor (aColor);
+ myDisabledMarkerAspect->SetMarkerScale(myDrawer->PointAspect()->Aspect()->MarkerScale());
+ myDisabledMarkerAspect->SetMarkerType (myLightSource->IsEnabled() ? Aspect_TOM_EMPTY : MarkerType (false));
+ myDisabledMarkerAspect->SetMarkerImage(MarkerImage (false));
+
+ myDrawer->ShadingAspect()->SetColor (aColor);
+ myDrawer->ArrowAspect() ->SetColor (aColor);
+ myDrawer->ArrowAspect()->Aspect()->ChangeFrontMaterial().SetColor (aColor);
+
+ if (myLightSource->Type() == Graphic3d_TOLS_DIRECTIONAL)
+ {
+ const Standard_Real anAngleTol = 2.0 * M_PI / 180.0;
+ Aspect_TypeOfMarker aDirMark = Aspect_TOM_EMPTY;
+ if (myLightSource->IsEnabled()
+ && myLightSource->IsHeadlight()
+ && myLightSource->Direction().IsParallel (gp::DZ(), anAngleTol))
+ {
+ aDirMark = myLightSource->Direction().IsOpposite (-gp::DZ(), anAngleTol) ? myOpposMarkerType : myCodirMarkerType;
+ }
+ myDrawer->ArrowAspect()->Aspect()->SetMarkerType (aDirMark);
+ }
+ SynchronizeAspects();
+}
+
+// =======================================================================
+// function : updateLightTransformPersistence
+// purpose :
+// =======================================================================
+void AIS_LightSource::updateLightTransformPersistence()
+{
+ Handle(Graphic3d_TransformPers) aTrsfPers = myTransformPersistence;
+ switch (myLightSource->Type())
+ {
+ case Graphic3d_TOLS_AMBIENT:
+ {
+ if (!myIsZoomable)
+ {
+ if (aTrsfPers.IsNull() || !aTrsfPers->IsTrihedronOr2d())
+ {
+ aTrsfPers = new Graphic3d_TransformPers (Graphic3d_TMF_TriedronPers, Aspect_TOTP_LEFT_UPPER, Graphic3d_Vec2i(50));
+ }
+ }
+ else
+ {
+ aTrsfPers.Nullify();
+ }
+ break;
+ }
+ case Graphic3d_TOLS_DIRECTIONAL:
+ {
+ Graphic3d_TransModeFlags aMode = myLightSource->IsHeadlight() ? Graphic3d_TMF_2d : Graphic3d_TMF_TriedronPers;
+ if (myIsZoomable)
+ {
+ aMode = myLightSource->IsHeadlight() ? Graphic3d_TMF_CameraPers : Graphic3d_TMF_None;
+ }
+ if (aMode != Graphic3d_TMF_None)
+ {
+ if (aTrsfPers.IsNull() || aTrsfPers->Mode() != aMode)
+ {
+ if (aMode == Graphic3d_TMF_CameraPers)
+ {
+ aTrsfPers = new Graphic3d_TransformPers (Graphic3d_TMF_CameraPers);
+ }
+ else
+ {
+ aTrsfPers = new Graphic3d_TransformPers (aMode, Aspect_TOTP_LEFT_UPPER, Graphic3d_Vec2i(50));
+ }
+ }
+ }
+ else
+ {
+ aTrsfPers.Nullify();
+ }
+ break;
+ }
+ case Graphic3d_TOLS_POSITIONAL:
+ case Graphic3d_TOLS_SPOT:
+ {
+ Graphic3d_TransModeFlags aMode = myLightSource->IsHeadlight()
+ ? Graphic3d_TMF_CameraPers
+ : (!myIsZoomable ? Graphic3d_TMF_ZoomPers : Graphic3d_TMF_None);
+ if (aMode != Graphic3d_TMF_None)
+ {
+ if (aTrsfPers.IsNull() || aTrsfPers->Mode() != aMode)
+ {
+ if (aMode == Graphic3d_TMF_CameraPers)
+ {
+ aTrsfPers = new Graphic3d_TransformPers (Graphic3d_TMF_CameraPers);
+ }
+ else
+ {
+ aTrsfPers = new Graphic3d_TransformPers (aMode, myLightSource->Position());
+ }
+ }
+ if (aMode == Graphic3d_TMF_ZoomPers)
+ {
+ aTrsfPers->SetAnchorPoint (myLightSource->Position());
+ }
+ }
+ else
+ {
+ aTrsfPers.Nullify();
+ }
+ break;
+ }
+ }
+
+ SetTransformPersistence (aTrsfPers);
+}
+
+// =======================================================================
+// function : updateLightLocalTransformation
+// purpose :
+// =======================================================================
+void AIS_LightSource::updateLightLocalTransformation()
+{
+ myLocalTransformation.Nullify();
+ switch (myLightSource->Type())
+ {
+ case Graphic3d_TOLS_AMBIENT:
+ {
+ if (myIsZoomable)
+ {
+ gp_Trsf aTrsf;
+ aTrsf.SetTranslation (gp::Origin(), myLightSource->Position());
+ myLocalTransformation = new TopLoc_Datum3D (aTrsf);
+ }
+ break;
+ }
+ case Graphic3d_TOLS_DIRECTIONAL:
+ {
+ const gp_Pnt aLightPos = (myIsZoomable && !myLightSource->IsHeadlight())
+ ? myLightSource->DisplayPosition()
+ : gp::Origin();
+ gp_Trsf aTrsf;
+ const gp_Ax2 anAx2 (aLightPos, -myLightSource->Direction());
+ aTrsf.SetTransformation (anAx2, gp_Ax3());
+ myLocalTransformation = new TopLoc_Datum3D (aTrsf);
+ break;
+ }
+ case Graphic3d_TOLS_POSITIONAL:
+ {
+ if (myIsZoomable)
+ {
+ gp_Trsf aTrsf;
+ aTrsf.SetTranslation (gp::Origin(), myLightSource->Position());
+ myLocalTransformation = new TopLoc_Datum3D (aTrsf);
+ }
+ break;
+ }
+ case Graphic3d_TOLS_SPOT:
+ {
+ gp_Trsf aTrsf;
+ const gp_Ax2 anAx2 (myIsZoomable ? myLightSource->Position() : gp::Origin(), -myLightSource->Direction());
+ aTrsf.SetTransformation (anAx2, gp_Ax3());
+ myLocalTransformation = new TopLoc_Datum3D (aTrsf);
+ break;
+ }
+ }
+ UpdateTransformation();
+}
+
+// =======================================================================
+// function : setLocalTransformation
+// purpose :
+// =======================================================================
+void AIS_LightSource::setLocalTransformation (const Handle(TopLoc_Datum3D)& theTrsf)
+{
+ const gp_Trsf aTrsf = theTrsf->Transformation();
+ switch (myLightSource->Type())
+ {
+ case Graphic3d_TOLS_AMBIENT:
+ {
+ break;
+ }
+ case Graphic3d_TOLS_DIRECTIONAL:
+ {
+ gp_Dir aNewDir = (-gp::DZ()).Transformed (aTrsf);
+ myLightSource->SetDirection (aNewDir);
+ if (myIsZoomable)
+ {
+ gp_Pnt aNewPos = gp::Origin().Transformed (aTrsf);
+ myLightSource->SetDisplayPosition (aNewPos);
+ }
+ break;
+ }
+ case Graphic3d_TOLS_POSITIONAL:
+ {
+ gp_Pnt aNewPos = gp::Origin().Transformed (aTrsf);
+ myLightSource->SetPosition (aNewPos);
+ break;
+ }
+ case Graphic3d_TOLS_SPOT:
+ {
+ gp_Pnt aNewPos = gp::Origin().Transformed (aTrsf);
+ myLightSource->SetPosition (aNewPos);
+
+ gp_Dir aNewDir = (-gp::DZ()).Transformed (aTrsf);
+ myLightSource->SetDirection (aNewDir);
+ break;
+ }
+ }
+
+ base_type::setLocalTransformation (new TopLoc_Datum3D (aTrsf));
+
+ updateLightAspects();
+ updateLightTransformPersistence();
+}
+
+// =======================================================================
+// function : Compute
+// purpose :
+// =======================================================================
+void AIS_LightSource::Compute (const Handle(PrsMgr_PresentationManager3d)& ,
+ const Handle(Prs3d_Presentation)& thePrs,
+ const Standard_Integer theMode)
+{
+ thePrs->SetInfiniteState (myInfiniteState);
+ if (theMode != 0
+ && theMode != 1)
+ {
+ return;
+ }
+
+ if (theMode == 0)
+ {
+ updateLightAspects();
+ updateLightTransformPersistence();
+ updateLightLocalTransformation();
+ }
+
+ switch (myLightSource->Type())
+ {
+ case Graphic3d_TOLS_AMBIENT: computeAmbient (thePrs, theMode); break;
+ case Graphic3d_TOLS_DIRECTIONAL: computeDirectional(thePrs, theMode); break;
+ case Graphic3d_TOLS_POSITIONAL: computePositional (thePrs, theMode); break;
+ case Graphic3d_TOLS_SPOT: computeSpot (thePrs, theMode); break;
+ }
+
+ if (myToDisplayName)
+ {
+ TCollection_AsciiString aPrefix = !myTransformPersistence.IsNull()
+ && myTransformPersistence->IsTrihedronOr2d()
+ ? "\n" : " ";
+ TCollection_AsciiString aName = aPrefix + myLightSource->Name();
+ Prs3d_Text::Draw (thePrs->NewGroup(), myDrawer->TextAspect(), aName, gp::Origin());
+ }
+}
+
+// =======================================================================
+// function : computeAmbient
+// purpose :
+// =======================================================================
+void AIS_LightSource::computeAmbient (const Handle(Prs3d_Presentation)& thePrs,
+ const Standard_Integer theMode)
+{
+ const gp_XYZ aLightPos = gp::Origin().XYZ();
+ if (theMode == 0)
+ {
+ Handle(Graphic3d_ArrayOfTriangles) aSphereArray = Prs3d_ToolSphere::Create (mySize * 0.25, myNbSplitsQuadric, myNbSplitsQuadric, gp_Trsf());
+ Handle(Graphic3d_Group) aSphereGroup = thePrs->NewGroup();
+ aSphereGroup->SetClosed (true);
+ aSphereGroup->SetGroupPrimitivesAspect (myDrawer->ShadingAspect()->Aspect());
+ aSphereGroup->AddPrimitiveArray (aSphereArray);
+ }
+ if (theMode == 0
+ || theMode == 1)
+ {
+ const Standard_Real aLen = mySize * 0.25;
+ const Standard_Integer aNbArrows = 6;
+ const gp_Dir aDirList[6] = { -gp::DX(), gp::DX(), -gp::DY(), gp::DY(), -gp::DZ(), gp::DZ() };
+
+ const Prs3d_ToolCylinder aCylTool (mySize * 0.1, 0.0, mySize * 0.2, myNbSplitsArrow, myNbSplitsArrow);
+ Handle(Graphic3d_ArrayOfTriangles) aTrisArray = new Graphic3d_ArrayOfTriangles (aNbArrows * aCylTool.VerticesNb(),
+ aNbArrows * aCylTool.TrianglesNb() * 3,
+ Graphic3d_ArrayFlags_VertexNormal);
+ Handle(Graphic3d_ArrayOfSegments) aLineArray = new Graphic3d_ArrayOfSegments (aNbArrows * 2);
+ for (Standard_Integer anArrIter = 0; anArrIter < aNbArrows; ++anArrIter)
+ {
+ const gp_Dir& aDir = aDirList[anArrIter];
+ const gp_XYZ aPnt = aLightPos + aDir.XYZ() * aLen;
+ if (!aLineArray.IsNull())
+ {
+ aLineArray->AddVertex (aPnt + aDir.XYZ() * aLen * 0.5);
+ aLineArray->AddVertex (aPnt + aDir.XYZ() * aLen * 1.5);
+ }
+ if (!aTrisArray.IsNull())
+ {
+ const gp_Ax3 aSystem (aPnt + aDir.XYZ() * aLen, -aDir);
+ gp_Trsf aTrsfCone;
+ aTrsfCone.SetTransformation (aSystem, gp_Ax3());
+ aCylTool.FillArray (aTrisArray, aTrsfCone);
+ }
+ }
+
+ if (!aLineArray.IsNull())
+ {
+ Handle(Graphic3d_Group) aDirGroupShadow = thePrs->NewGroup();
+ aDirGroupShadow->SetGroupPrimitivesAspect (myArrowLineAspectShadow);
+ aDirGroupShadow->AddPrimitiveArray (aLineArray);
+ }
+ if (!aTrisArray.IsNull())
+ {
+ Handle(Graphic3d_Group) anArrowGroup = thePrs->NewGroup();
+ anArrowGroup->SetClosed (true);
+ anArrowGroup->SetGroupPrimitivesAspect (myDrawer->ArrowAspect()->Aspect());
+ anArrowGroup->AddPrimitiveArray (aTrisArray);
+ }
+ }
+
+ {
+ Handle(Graphic3d_ArrayOfPoints) aPoints = new Graphic3d_ArrayOfPoints (1);
+ aPoints->AddVertex (aLightPos);
+ Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
+ aGroup->SetGroupPrimitivesAspect (theMode == 1 ? myDrawer->PointAspect()->Aspect() : myDisabledMarkerAspect);
+ aGroup->AddPrimitiveArray (aPoints);
+ }
+}
+
+// =======================================================================
+// function : computeDirectional
+// purpose :
+// =======================================================================
+void AIS_LightSource::computeDirectional (const Handle(Prs3d_Presentation)& thePrs,
+ const Standard_Integer theMode)
+{
+ const Standard_Real aDistance = mySize * 0.5;
+ const Standard_Real aStep = aDistance * 0.5;
+
+ // light source direction is set to local transformation
+ const gp_Dir aLightDir = -gp::DZ();
+ const gp_XYZ aLightPos = -aStep * aLightDir.XYZ();
+
+ Standard_Integer aNbArrows = 1;
+ if (myNbArrows >= 9) { aNbArrows = 9; }
+ else if (myNbArrows >= 5) { aNbArrows = 5; }
+ else if (myNbArrows >= 3) { aNbArrows = 3; }
+ TColgp_Array1OfPnt aPoints (1, aNbArrows);
+ {
+ const gp_Ax2 anAxes (gp::Origin(), aLightDir);
+ const gp_XYZ aDY = anAxes.YDirection().XYZ() * aStep;
+ const gp_XYZ aDX = anAxes.XDirection().XYZ() * aStep;
+ const gp_XYZ aDXY = aDX + aDY;
+ switch (aNbArrows)
+ {
+ case 9:
+ {
+ aPoints.SetValue (6, aLightPos + aDY);
+ aPoints.SetValue (7, aLightPos + aDX);
+ aPoints.SetValue (8, aLightPos - aDY);
+ aPoints.SetValue (9, aLightPos - aDX);
+ }
+ Standard_FALLTHROUGH
+ case 5:
+ {
+ aPoints.SetValue (4, aLightPos - aDY + aDX);
+ aPoints.SetValue (5, aLightPos + aDY - aDX);
+ }
+ Standard_FALLTHROUGH
+ case 3:
+ {
+ aPoints.SetValue (2, aLightPos + aDXY);
+ aPoints.SetValue (3, aLightPos - aDXY);
+ }
+ Standard_FALLTHROUGH
+ case 1:
+ {
+ aPoints.SetValue (1, aLightPos);
+ break;
+ }
+ }
+ }
+
+ const Prs3d_ToolCylinder aCylTool (aDistance * 0.1, 0.0, aDistance * 0.2, myNbSplitsArrow, myNbSplitsArrow);
+ Handle(Graphic3d_ArrayOfTriangles) aTrisArray;
+ if (theMode == 0)
+ {
+ aTrisArray = new Graphic3d_ArrayOfTriangles (aNbArrows * aCylTool.VerticesNb(),
+ aNbArrows * aCylTool.TrianglesNb() * 3,
+ Graphic3d_ArrayFlags_VertexNormal);
+ }
+ Handle(Graphic3d_ArrayOfPoints) aPntArray = new Graphic3d_ArrayOfPoints (aNbArrows);
+ Handle(Graphic3d_ArrayOfSegments) aLineArray = new Graphic3d_ArrayOfSegments (aNbArrows * 2);
+ for (Standard_Integer aPntIter = aPoints.Lower(); aPntIter <= aPoints.Upper(); ++aPntIter)
+ {
+ const gp_Pnt aPnt = aPoints.Value (aPntIter);
+ if (!aPntArray.IsNull())
+ {
+ aPntArray->AddVertex (aPnt);
+ }
+ if (!aLineArray.IsNull())
+ {
+ aLineArray->AddVertex (aPnt);
+ aLineArray->AddVertex (gp_Pnt (aPnt.XYZ() + aLightDir.XYZ() * aDistance));
+ }
+ if (!aTrisArray.IsNull())
+ {
+ const gp_Ax3 aSystem (aPnt.XYZ() + aLightDir.XYZ() * aDistance, aLightDir);
+ gp_Trsf aTrsfCone;
+ aTrsfCone.SetTransformation (aSystem, gp_Ax3());
+ aCylTool.FillArray (aTrisArray, aTrsfCone);
+ }
+ }
+
+ if (!aLineArray.IsNull() && theMode == 0)
+ {
+ Handle(Graphic3d_Group) aDirGroupShadow = thePrs->NewGroup();
+ aDirGroupShadow->SetGroupPrimitivesAspect (myArrowLineAspectShadow);
+ aDirGroupShadow->AddPrimitiveArray (aLineArray);
+ }
+ if (!aLineArray.IsNull())
+ {
+ Handle(Graphic3d_Group) aDirGroup = thePrs->NewGroup();
+ aDirGroup->SetGroupPrimitivesAspect (myDrawer->ArrowAspect()->Aspect());
+ aDirGroup->AddPrimitiveArray (aLineArray);
+ }
+ if (!aTrisArray.IsNull())
+ {
+ Handle(Graphic3d_Group) anArrowGroup = thePrs->NewGroup();
+ anArrowGroup->SetClosed (true);
+ anArrowGroup->SetGroupPrimitivesAspect (myDrawer->ArrowAspect()->Aspect());
+ anArrowGroup->AddPrimitiveArray (aTrisArray);
+ }
+ if (!aPntArray.IsNull())
+ {
+ Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
+ aGroup->SetGroupPrimitivesAspect (myDrawer->ArrowAspect()->Aspect());
+ aGroup->AddPrimitiveArray (aPntArray);
+ }
+ {
+ Handle(Graphic3d_ArrayOfPoints) aPntArray2 = new Graphic3d_ArrayOfPoints (1);
+ aPntArray2->AddVertex (aLightPos);
+ Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
+ aGroup->SetGroupPrimitivesAspect (myDisabledMarkerAspect);
+ aGroup->AddPrimitiveArray (aPntArray2);
+ }
+}
+
+// =======================================================================
+// function : computePositional
+// purpose :
+// =======================================================================
+void AIS_LightSource::computePositional (const Handle(Prs3d_Presentation)& thePrs,
+ const Standard_Integer theMode)
+{
+ // light source position is set to local transformation
+ const gp_XYZ aLightPos = gp::Origin().XYZ();
+ const Standard_Real aRadius = (myIsZoomable && myLightSource->HasRange()) ? myLightSource->Range() : 0.0;
+ if (theMode == 0
+ && aRadius > 0.0
+ && myToDisplayRange)
+ {
+ Handle(Graphic3d_ArrayOfTriangles) aPosRangeArray = Prs3d_ToolSphere::Create (aRadius, myNbSplitsQuadric, myNbSplitsQuadric, gp_Trsf());
+ Handle(Graphic3d_Group) aRangeGroup = thePrs->NewGroup();
+ aRangeGroup->SetClosed (true);
+ aRangeGroup->SetGroupPrimitivesAspect (myDrawer->ShadingAspect()->Aspect());
+ aRangeGroup->AddPrimitiveArray (aPosRangeArray);
+ }
+ {
+ Handle(Graphic3d_ArrayOfPoints) aPoints = new Graphic3d_ArrayOfPoints (1);
+ aPoints->AddVertex (aLightPos);
+ Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
+ aGroup->SetGroupPrimitivesAspect (myDrawer->PointAspect()->Aspect());
+ aGroup->AddPrimitiveArray (aPoints);
+ }
+}
+
+// =======================================================================
+// function : computeSpot
+// purpose :
+// =======================================================================
+void AIS_LightSource::computeSpot (const Handle(Prs3d_Presentation)& thePrs,
+ const Standard_Integer theMode)
+{
+ // light source position and direction are set to local transformation
+ const gp_Dir aLightDir = -gp::DZ();
+ const gp_XYZ aLightPos = gp::Origin().XYZ();
+ const Standard_Real aDistance = (myIsZoomable && myLightSource->HasRange()) ? myLightSource->Range() : mySize;
+ {
+ Handle(Graphic3d_ArrayOfPoints) aPoints = new Graphic3d_ArrayOfPoints (1);
+ aPoints->AddVertex (aLightPos);
+
+ Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
+ aGroup->SetGroupPrimitivesAspect (myDrawer->PointAspect()->Aspect());
+ aGroup->AddPrimitiveArray (aPoints);
+ }
+
+ {
+ Handle(Graphic3d_ArrayOfSegments) aDirArray = new Graphic3d_ArrayOfSegments (2);
+ aDirArray->AddVertex (aLightPos);
+ aDirArray->AddVertex (gp_Pnt (aLightPos + aLightDir.XYZ() * aDistance));
+
+ Handle(Graphic3d_Group) aDirGroupShadow = thePrs->NewGroup();
+ aDirGroupShadow->SetClosed (true);
+ aDirGroupShadow->SetGroupPrimitivesAspect (myArrowLineAspectShadow);
+ aDirGroupShadow->AddPrimitiveArray (aDirArray);
+
+ Handle(Graphic3d_Group) aDirGroup = thePrs->NewGroup();
+ aDirGroup->SetClosed (true);
+ aDirGroup->SetGroupPrimitivesAspect (myDrawer->ArrowAspect()->Aspect());
+ aDirGroup->AddPrimitiveArray (aDirArray);
+ }
+
+ if (theMode == 0
+ && myToDisplayRange)
+ {
+ const Standard_ShortReal aHalfAngle = myLightSource->Angle() / 2.0f;
+ const Standard_Real aRadius = aDistance * Tan (aHalfAngle);
+ gp_Ax3 aSystem (aLightPos + aLightDir.XYZ() * aDistance, -aLightDir);
+ gp_Trsf aTrsfCone;
+ aTrsfCone.SetTransformation (aSystem, gp_Ax3());
+ Handle(Graphic3d_ArrayOfTriangles) aSpotRangeArray = Prs3d_ToolCylinder::Create (aRadius, 0.0, aDistance,
+ myNbSplitsQuadric, myNbSplitsQuadric, aTrsfCone);
+
+ Handle(Graphic3d_Group) aRangeGroup = thePrs->NewGroup();
+ aRangeGroup->SetClosed (true);
+ aRangeGroup->SetGroupPrimitivesAspect (myDrawer->ShadingAspect()->Aspect());
+ aRangeGroup->AddPrimitiveArray (aSpotRangeArray);
+ }
+}
+
+// =======================================================================
+// function : ComputeSelection
+// purpose :
+// =======================================================================
+void AIS_LightSource::ComputeSelection (const Handle(SelectMgr_Selection)& theSel,
+ const Standard_Integer theMode)
+{
+ if (theMode != 0)
+ {
+ return;
+ }
+
+ Handle(AIS_LightSourceOwner) anEntityOwner = new AIS_LightSourceOwner (this, 15);
+ {
+ Handle(Select3D_SensitivePoint) aSensPosition = new Select3D_SensitivePoint (anEntityOwner, gp::Origin());
+ aSensPosition->SetSensitivityFactor (12);
+ if (!myTransformPersistence.IsNull()
+ && myTransformPersistence->IsTrihedronOr2d())
+ {
+ aSensPosition->SetSensitivityFactor (Max (12, Standard_Integer (mySize * 0.5)));
+ }
+ theSel->Add (aSensPosition);
+ }
+}
--- /dev/null
+// Created on: 2020-09-07
+// Created by: Maria KRYLOVA
+// Copyright (c) 2020 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _AIS_LightSource_HeaderFile
+#define _AIS_LightSource_HeaderFile
+
+#include <AIS_InteractiveObject.hxx>
+#include <Graphic3d_CLight.hxx>
+#include <SelectMgr_EntityOwner.hxx>
+
+class Prs3d_ShadingAspect;
+
+//! Interactive object for a light source.
+//! Each type of light source has it's own presentation:
+//! - Ambient light is displayed as a sphere at view corner;
+//! - Positional light is represented by a sphere or marker;
+//! - Spot light is represented by a cone;
+//! - Directional light is represented by a set of arrows at the corner of view.
+//! In addition, light source name could be displayed, and clicking on presentation will enable/disable light.
+class AIS_LightSource : public AIS_InteractiveObject
+{
+ friend class AIS_LightSourceOwner;
+ DEFINE_STANDARD_RTTIEXT(AIS_LightSource, AIS_InteractiveObject)
+public:
+
+ //! Initializes the light source by copying Graphic3d_CLight settings.
+ Standard_EXPORT AIS_LightSource (const Handle(Graphic3d_CLight)& theLightSource);
+
+ //! Returns the light.
+ const Handle(Graphic3d_CLight)& Light() const { return myLightSource; }
+
+ //! Set the light.
+ void SetLight (const Handle(Graphic3d_CLight)& theLight)
+ {
+ myLightSource = theLight;
+ SetToUpdate();
+ }
+
+public: //! @name Light properties
+
+ //! Returns TRUE if the light source name should be displayed; TRUE by default.
+ Standard_Boolean ToDisplayName() const { return myToDisplayName; }
+
+ //! Show/hide light source name.
+ void SetDisplayName(Standard_Boolean theToDisplay)
+ {
+ if (myToDisplayName != theToDisplay)
+ {
+ myToDisplayName = theToDisplay;
+ SetToUpdate();
+ }
+ }
+
+ //! Returns TRUE to display light source range as sphere (positional light) or cone (spot light); TRUE by default.
+ //! Has no effect for non-zoomable presentation.
+ Standard_Boolean ToDisplayRange() const { return myToDisplayRange; }
+
+ //! Show/hide light source range shaded presentation.
+ void SetDisplayRange (Standard_Boolean theToDisplay)
+ {
+ if (myToDisplayRange != theToDisplay)
+ {
+ myToDisplayRange = theToDisplay;
+ SetToUpdate();
+ }
+ }
+
+ //! Returns the size of presentation; 50 by default.
+ Standard_Real Size() const { return mySize; }
+
+ //! Sets the size of presentation.
+ void SetSize (Standard_Real theSize)
+ {
+ if (mySize != theSize)
+ {
+ mySize = 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.
+ bool IsZoomable() const { return myIsZoomable; }
+
+ //! Sets if transform-persistence is allowed.
+ void SetZoomable (bool theIsZoomable)
+ {
+ if (myIsZoomable != theIsZoomable)
+ {
+ myIsZoomable = theIsZoomable;
+ SetToUpdate();
+ }
+ }
+
+ //! Returns TRUE if mouse click will turn light on/off; TRUE by default.
+ bool ToSwitchOnClick() const { return myToSwitchOnClick; }
+
+ //! Sets if mouse click should turn light on/off.
+ void SetSwitchOnClick (bool theToHandle) { myToSwitchOnClick = theToHandle; }
+
+ //! Returns a number of directional light arrows to display; 5 by default.
+ Standard_Integer NbArrows() const { return myNbArrows; }
+
+ //! Returns a number of directional light arrows to display (supported values: 1, 3, 5, 9).
+ void SetNbArrows (Standard_Integer theNbArrows)
+ {
+ if (myNbArrows != theNbArrows)
+ {
+ myNbArrows = theNbArrows;
+ SetToUpdate();
+ }
+ }
+
+ //! Returns light source icon.
+ //! @param theIsEnabled [in] marker index for enabled/disabled light source states
+ const Handle(Graphic3d_MarkerImage)& MarkerImage (bool theIsEnabled) const { return myMarkerImages[theIsEnabled ? 1 : 0]; }
+
+ //! Returns light source icon.
+ //! @param theIsEnabled [in] marker index for enabled/disabled light source states
+ Aspect_TypeOfMarker MarkerType (bool theIsEnabled) const { return myMarkerTypes[theIsEnabled ? 1 : 0]; }
+
+ //! Sets custom icon to light source.
+ void SetMarkerImage (const Handle(Graphic3d_MarkerImage)& theImage,
+ bool theIsEnabled)
+ {
+ myMarkerImages[theIsEnabled ? 1 : 0] = theImage;
+ myMarkerTypes [theIsEnabled ? 1 : 0] = !theImage.IsNull()
+ ? Aspect_TOM_USERDEFINED
+ : (theIsEnabled ? Aspect_TOM_O_POINT : Aspect_TOM_O_X);
+ }
+
+ //! Sets standard icon to light source.
+ void SetMarkerType (Aspect_TypeOfMarker theType,
+ bool theIsEnabled)
+ {
+ myMarkerTypes[theIsEnabled ? 1 : 0] = theType;
+ }
+
+ //! Returns tessellation level for quadric surfaces; 30 by default.
+ Standard_Integer NbSplitsQuadric() const { return myNbSplitsQuadric; }
+
+ //! Sets tessellation level for quadric surfaces.
+ void SetNbSplitsQuadric (Standard_Integer theNbSplits) { myNbSplitsQuadric = theNbSplits; }
+
+ //! Returns tessellation level for arrows; 20 by default.
+ Standard_Integer NbSplitsArrow() const { return myNbSplitsArrow; }
+
+ //! Sets tessellation level for arrows.
+ void SetNbSplitsArrow (Standard_Integer theNbSplits) { myNbSplitsArrow = theNbSplits; }
+
+ //! Returns kind of the object.
+ virtual AIS_KindOfInteractive Type() const Standard_OVERRIDE { return AIS_KindOfInteractive_LightSource; }
+
+protected:
+
+ //! Return true if specified display mode is supported: 0 for main presentation and 1 for highlight.
+ virtual Standard_Boolean AcceptDisplayMode (const Standard_Integer theMode) const Standard_OVERRIDE
+ {
+ return theMode == 0
+ || theMode == 1;
+ }
+
+ //! Computes selection sensitive zones(triangulation) for light source presentation.
+ Standard_EXPORT virtual void Compute (const Handle(PrsMgr_PresentationManager3d)& thePrsMgr,
+ const Handle(Prs3d_Presentation)& thePrs,
+ const Standard_Integer theMode) Standard_OVERRIDE;
+
+ //! Fills presentation.
+ Standard_EXPORT virtual void ComputeSelection (const Handle(SelectMgr_Selection)& theSel,
+ const Standard_Integer theMode) 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;
+
+ //! Updates local transformation basing on a type of light source.
+ Standard_EXPORT virtual void updateLightLocalTransformation();
+
+ //! Updates transform persistence basing on a type of light source.
+ Standard_EXPORT virtual void updateLightTransformPersistence();
+
+ //! Sets color of light.
+ Standard_EXPORT virtual void updateLightAspects();
+
+ //! Compute ambient light source presentation as a sphere at view corner.
+ Standard_EXPORT virtual void computeAmbient (const Handle(Prs3d_Presentation)& thePrs,
+ const Standard_Integer theMode);
+
+ //! Compute directional light source presentation as a set of arrows at view corner.
+ Standard_EXPORT virtual void computeDirectional (const Handle(Prs3d_Presentation)& thePrs,
+ const Standard_Integer theMode);
+
+ //! Compute positional light source presentation as a sphere of either fixed size (no range) or of size representing a maximum range.
+ Standard_EXPORT virtual void computePositional (const Handle(Prs3d_Presentation)& thePrs,
+ const Standard_Integer theMode);
+
+ //! Compute spot light source presentation as a cone.
+ Standard_EXPORT virtual void computeSpot (const Handle(Prs3d_Presentation)& thePrs,
+ const Standard_Integer theMode);
+
+protected:
+
+ Handle(Graphic3d_CLight) myLightSource; //!< displayed light source
+
+ 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
+ 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
+
+};
+
+//! Owner of AIS_LightSource presentation.
+class AIS_LightSourceOwner : public SelectMgr_EntityOwner
+{
+ DEFINE_STANDARD_RTTIEXT(AIS_LightSourceOwner, SelectMgr_EntityOwner)
+public:
+
+ //! Main constructor.
+ Standard_EXPORT AIS_LightSourceOwner (const Handle(AIS_LightSource)& theObject,
+ Standard_Integer thePriority = 5);
+
+ //! Handle mouse button click event.
+ Standard_EXPORT virtual Standard_Boolean HandleMouseClick (const Graphic3d_Vec2i& thePoint,
+ Aspect_VKeyMouse theButton,
+ Aspect_VKeyFlags theModifiers,
+ bool theIsDoubleClick) Standard_OVERRIDE;
+
+};
+
+#endif // _AIS_LightSource_HeaderFile
AIS_InteractiveObject.cxx
AIS_InteractiveObject.hxx
AIS_KindOfInteractive.hxx
+AIS_LightSource.cxx
+AIS_LightSource.hxx
AIS_Line.cxx
AIS_Line.hxx
AIS_ListIteratorOfListOfInteractive.hxx
{
Standard_ProgramError_Raise_if (myType != Graphic3d_TOLS_SPOT
&& myType != Graphic3d_TOLS_POSITIONAL,
- "Graphic3d_CLight::SetDirection(), incorrect light type");
+ "Graphic3d_CLight::SetPosition(), incorrect light type");
+ updateRevisionIf (!myPosition.IsEqual (thePosition, gp::Resolution()));
+ myPosition = thePosition;
+}
+
+// =======================================================================
+// function : SetDisplayPosition
+// purpose :
+// =======================================================================
+void Graphic3d_CLight::SetDisplayPosition (const gp_Pnt& thePosition)
+{
+ Standard_ProgramError_Raise_if (myType == Graphic3d_TOLS_AMBIENT,
+ "Graphic3d_CLight::SetDisplayPosition(), incorrect light type");
updateRevisionIf (!myPosition.IsEqual (thePosition, gp::Resolution()));
myPosition = thePosition;
}
//! Sets direction of directional/spot light.
void SetDirection (Standard_Real theVx, Standard_Real theVy, Standard_Real theVz) { SetDirection (gp_Dir (theVx, theVy, theVz)); }
+ //! Returns location of positional/spot/directional light, which is the same as returned by Position().
+ const gp_Pnt& DisplayPosition() const { return myPosition; }
+
+ //! Setup location of positional/spot/directional light,
+ //! which is the same as SetPosition() but allows directional light source
+ //! (technically having no position, but this point can be used for displaying light source presentation).
+ Standard_EXPORT void SetDisplayPosition (const gp_Pnt& thePosition);
+
//! @name spotlight additional definition parameters
public:
//! Modifies the smoothing angle (in radians) of directional light source; should be within range [0.0, M_PI/2].
Standard_EXPORT void SetSmoothAngle (Standard_ShortReal theValue);
+ //! Returns TRUE if maximum distance of point light source is defined.
+ bool HasRange() const { return myDirection.w() != 0.0f; }
+
//! Returns maximum distance on which point light source affects to objects and is considered during illumination calculations.
//! 0.0 means disabling range considering at all without any distance limits.
//! Has sense only for point light sources (positional and spot).
Graphic3d_TMF_RotatePers = 0x0008, //!< object does not rotate;
Graphic3d_TMF_TriedronPers = 0x0020, //!< object behaves like trihedron - it is fixed at the corner of view and does not resizing (but rotating)
Graphic3d_TMF_2d = 0x0040, //!< object is defined in 2D screen coordinates (pixels) and does not resize, pan and rotate
+ Graphic3d_TMF_CameraPers = 0x0080, //!< object is in front of the camera
Graphic3d_TMF_ZoomRotatePers = Graphic3d_TMF_ZoomPers
| Graphic3d_TMF_RotatePers //!< object doesn't resize and rotate
};
{
SetPersistence (theMode, Aspect_TOTP_LEFT_LOWER, Graphic3d_Vec2i (0, 0));
}
+ else if (theMode == Graphic3d_TMF_CameraPers)
+ {
+ myMode = theMode;
+ }
else
{
throw Standard_ProgramError("Graphic3d_TransformPers::SetPersistence(), wrong persistence mode.");
Graphic3d_TransformUtils::Scale (theWorldView, T(aScale), T(aScale), T(aScale));
return;
}
+ else if ((myMode & Graphic3d_TMF_CameraPers) != 0)
+ {
+ theWorldView.InitIdentity();
+ }
else
{
// Compute reference point for transformation in untransformed projection space.
#endif
bool anOldCastShadows = false;
+#ifdef GL_DEPTH_CLAMP
+ bool toRestoreDepthClamp = false;
+#endif
if (!myTrsfPers.IsNull())
{
// temporarily disable shadows on non-3d objects
}
}
#endif
+
+ #ifdef GL_DEPTH_CLAMP
+ if (myTrsfPers->Mode() == Graphic3d_TMF_CameraPers
+ && aCtx->arbDepthClamp)
+ {
+ toRestoreDepthClamp = true;
+ aCtx->core11fwd->glEnable (GL_DEPTH_CLAMP);
+ }
+ #endif
}
// Take into account transform persistence
{
aCtx->WorldViewState.Pop();
aCtx->ShaderManager()->SetCastShadows (anOldCastShadows);
+ #ifdef GL_DEPTH_CLAMP
+ if (toRestoreDepthClamp) { aCtx->core11fwd->glDisable (GL_DEPTH_CLAMP); }
+ #endif
}
// Restore named status
Standard_EXPORT void FillArray (Handle(Graphic3d_ArrayOfTriangles)& theArray,
const gp_Trsf& theTrsf) const;
+ //! Return number of triangles in generated presentation.
+ Standard_Integer TrianglesNb() const { return mySlicesNb * myStacksNb * 2; }
+
+ //! Return number of vertices in generated presentation.
+ Standard_Integer VerticesNb (bool theIsIndexed = true) const
+ {
+ return theIsIndexed
+ ? (mySlicesNb + 1) * (myStacksNb + 1)
+ : TrianglesNb() * 3;
+ }
+
public:
//! Generate primitives for 3D quadric surface presentation.
protected:
- //! Return number of triangles in generated presentation.
- Standard_Integer TrianglesNb() const
- {
- return mySlicesNb * myStacksNb * 2;
- }
-
- //! Return number of vertices in generated presentation.
- Standard_Integer VerticesNb (const Standard_Boolean theIsIndexed = Standard_True) const
- {
- return theIsIndexed
- ? (mySlicesNb + 1) * (myStacksNb + 1)
- : TrianglesNb() * 3;
- }
-
//! Redefine this method to generate vertex at given parameters.
virtual gp_Pnt Vertex (const Standard_Real theU, const Standard_Real theV) const = 0;
#include <AIS_CameraFrustum.hxx>
#include <AIS_ColorScale.hxx>
#include <AIS_InteractiveContext.hxx>
+#include <AIS_LightSource.hxx>
#include <AIS_ListOfInteractive.hxx>
#include <AIS_ListIteratorOfListOfInteractive.hxx>
#include <AIS_Manipulator.hxx>
}
}
+static Handle(AIS_LightSource) findLightPrs (const Handle(V3d_Light)& theLight,
+ const bool theToShowErrors = true)
+{
+ if (theLight.IsNull())
+ {
+ if (theToShowErrors)
+ {
+ Message::SendFail() << "Syntax error: no active light source to find presentation";
+ }
+ return Handle(AIS_LightSource)();
+ }
+
+ Handle(AIS_InteractiveObject) anObject;
+ GetMapOfAIS().Find2 (theLight->Name(), anObject);
+ Handle(AIS_LightSource) aLightSource = Handle(AIS_LightSource)::DownCast (anObject);
+ if (aLightSource.IsNull())
+ {
+ if (theToShowErrors)
+ {
+ Message::SendFail() << "Syntax error: could not find '" << theLight->Name() << "' AIS object";
+ }
+ }
+ return aLightSource;
+}
+
//===============================================================================================
//function : VLight
//purpose :
}
}
- Handle(V3d_Light) aLightNew;
- Handle(V3d_Light) aLightOld;
+ Handle(V3d_Light) aLightNew, aLightOld;
Graphic3d_ZLayerId aLayer = Graphic3d_ZLayerId_UNKNOWN;
Standard_Boolean isGlobal = Standard_True;
Standard_Boolean toCreate = Standard_False;
if (aLayer == Graphic3d_ZLayerId_UNKNOWN)
{
+ ViewerTest_DoubleMapOfInteractiveAndName aMap = GetMapOfAIS();
for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More();)
{
Handle(V3d_Light) aLight = aLightIter.Value();
+ if (Handle(AIS_LightSource) aLightSourceDel = findLightPrs (aLight, false))
+ {
+ ViewerTest::GetAISContext()->Remove (aLightSourceDel, false);
+ GetMapOfAIS().UnBind2 (aLight->Name());
+ }
aViewer->DelLight (aLight);
aLightIter = aView->ActiveLightIterator();
}
return 1;
}
}
- else if (anArgCase.IsEqual ("DEL")
- || anArgCase.IsEqual ("DELETE")
- || anArgCase.IsEqual ("-DEL")
- || anArgCase.IsEqual ("-DELETE"))
+ else if (anArgCase == "-DISPLAY"
+ || anArgCase == "-DISP"
+ || anArgCase == "-PRESENTATION"
+ || anArgCase == "-PRS")
+ {
+ if (aLightCurr.IsNull())
+ {
+ Message::SendFail() << "Syntax error at argument '" << anArg << "'";
+ return 1;
+ }
+
+ TCollection_AsciiString aLightName = aLightCurr->Name();
+ if (++anArgIt > theArgsNb
+ && aLightName.IsEmpty())
+ {
+ Message::SendFail() << "Syntax error at argument '" << anArg << "'";
+ return 1;
+ }
+ if (anArgIt < theArgsNb)
+ {
+ if (theArgVec[anArgIt][0] != '-')
+ {
+ aLightName = theArgVec[anArgIt];
+ aLightCurr->SetName (aLightName);
+ }
+ else
+ {
+ --anArgIt;
+ }
+ }
+ if (aLightName.IsEmpty())
+ {
+ Message::SendFail() << "Syntax error at argument '" << anArg << "'";
+ return 1;
+ }
+ ViewerTest::Display (aLightName, new AIS_LightSource (aLightCurr), false);
+ }
+ else if (anArgCase == "DEL"
+ || anArgCase == "DELETE"
+ || anArgCase == "-DEL"
+ || anArgCase == "-DELETE"
+ || anArgCase == "-REMOVE")
{
Handle(V3d_Light) aLightDel;
if (++anArgIt >= theArgsNb)
if (aLayer == Graphic3d_ZLayerId_UNKNOWN)
{
+ if (Handle(AIS_LightSource) aLightSourceDel = findLightPrs (aLightDel, false))
+ {
+ ViewerTest::GetAISContext()->Remove (aLightSourceDel, false);
+ GetMapOfAIS().UnBind2 (aLightDel->Name());
+ }
aViewer->DelLight (aLightDel);
}
}
}
aLightCurr->SetColor (aColor);
}
- else if (anArgCase.IsEqual ("POS")
- || anArgCase.IsEqual ("POSITION")
- || anArgCase.IsEqual ("-POS")
- || anArgCase.IsEqual ("-POSITION"))
+ else if (anArgCase == "POS"
+ || anArgCase == "POSITION"
+ || anArgCase == "-POS"
+ || anArgCase == "-POSITION"
+ || anArgCase == "-PRSPOSITION"
+ || anArgCase == "-PRSPOS")
{
+ gp_XYZ aPosXYZ;
if ((anArgIt + 3) >= theArgsNb
- || aLightCurr.IsNull()
- || (aLightCurr->Type() != Graphic3d_TOLS_POSITIONAL
- && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
+ || !parseXYZ (theArgVec + anArgIt + 1, aPosXYZ)
+ || aLightCurr.IsNull())
{
Message::SendFail() << "Syntax error at argument '" << anArg << "'";
return 1;
}
- anXYZ[0] = Atof (theArgVec[++anArgIt]);
- anXYZ[1] = Atof (theArgVec[++anArgIt]);
- anXYZ[2] = Atof (theArgVec[++anArgIt]);
- aLightCurr->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
+ anArgIt += 3;
+ if (anArgCase == "-PRSPOSITION"
+ || anArgCase == "-PRSPOS")
+ {
+ aLightCurr->SetDisplayPosition (aPosXYZ);
+ }
+ else
+ {
+ if (aLightCurr->Type() != Graphic3d_TOLS_POSITIONAL
+ && aLightCurr->Type() != Graphic3d_TOLS_SPOT)
+ {
+ Message::SendFail() << "Syntax error at argument '" << anArg << "'";
+ return 1;
+ }
+
+ aLightCurr->SetPosition (aPosXYZ);
+ }
}
else if (anArgCase.IsEqual ("DIR")
|| anArgCase.IsEqual ("DIRECTION")
|| anArgCase.IsEqual ("-DIR")
|| anArgCase.IsEqual ("-DIRECTION"))
{
+ gp_XYZ aDirXYZ;
if ((anArgIt + 3) >= theArgsNb
+ || !parseXYZ (theArgVec + anArgIt + 1, aDirXYZ)
|| aLightCurr.IsNull()
|| (aLightCurr->Type() != Graphic3d_TOLS_DIRECTIONAL
&& aLightCurr->Type() != Graphic3d_TOLS_SPOT))
return 1;
}
- anXYZ[0] = Atof (theArgVec[++anArgIt]);
- anXYZ[1] = Atof (theArgVec[++anArgIt]);
- anXYZ[2] = Atof (theArgVec[++anArgIt]);
- aLightCurr->SetDirection (anXYZ[0], anXYZ[1], anXYZ[2]);
+ anArgIt += 3;
+ aLightCurr->SetDirection (gp_Dir (aDirXYZ));
}
else if (anArgCase.IsEqual ("SM")
|| anArgCase.IsEqual ("SMOOTHNESS")
Message::SendFail() << "Syntax error at argument '" << anArg << "'";
return 1;
}
-
Standard_ShortReal anAngle = (Standard_ShortReal )Atof (theArgVec[anArgIt]);
- aLightCurr->SetAngle (Standard_ShortReal (anAngle / 180.0 * M_PI));
+ anAngle = (Standard_ShortReal (anAngle / 180.0 * M_PI));
+ aLightCurr->SetAngle (anAngle);
}
else if (anArgCase.IsEqual ("CONSTATTEN")
|| anArgCase.IsEqual ("CONSTATTENUATION")
Message::SendFail() << "Syntax error at argument '" << anArg << "'";
return 1;
}
-
- aLightCurr->SetRange ((Standard_ShortReal)Atof (theArgVec[anArgIt]));
+ Standard_ShortReal aRange ((Standard_ShortReal)Atof (theArgVec[anArgIt]));
+ aLightCurr->SetRange (aRange);
}
else if (anArgCase.IsEqual ("HEAD")
|| anArgCase.IsEqual ("HEADLIGHT")
}
aLightCurr->SetHeadlight (isHeadLight);
}
+ else if (anArgCase.IsEqual ("NAME")
+ || anArgCase.IsEqual ("-NAME"))
+ {
+ if ((anArgIt + 1) >= theArgsNb
+ || aLightCurr.IsNull())
+ {
+ Message::SendFail() << "Syntax error at argument '" << anArg << "'";
+ return 1;
+ }
+ aName = theArgVec[++anArgIt];
+ aLightCurr->SetName (aName);
+ }
+ else if (anArgCase == "-SHOWZOOMABLE"
+ || anArgCase == "-PRSZOOMABLE"
+ || anArgCase == "-ZOOMABLE")
+ {
+ if (aLightCurr.IsNull())
+ {
+ Message::SendFail() << "Syntax error at argument '" << anArg << "'";
+ return 1;
+ }
+
+ if (Handle(AIS_LightSource) aLightSource = findLightPrs (aLightCurr))
+ {
+ const bool isZoomable = Draw::ParseOnOffIterator (theArgsNb, theArgVec, anArgIt);
+ aLightSource->SetZoomable (isZoomable);
+ }
+ else
+ {
+ return 1;
+ }
+ }
+ else if (anArgCase == "-SHOWNAME"
+ || anArgCase == "-PRSNAME")
+ {
+ if (aLightCurr.IsNull())
+ {
+ Message::SendFail() << "Syntax error at argument '" << anArg << "'";
+ return 1;
+ }
+
+ if (Handle(AIS_LightSource) aLightSource = findLightPrs (aLightCurr))
+ {
+ const bool toDisplay = Draw::ParseOnOffIterator (theArgsNb, theArgVec, anArgIt);
+ aLightSource->SetDisplayName (toDisplay);
+ }
+ else
+ {
+ return 1;
+ }
+ }
+ else if (anArgCase == "-SHOWRANGE"
+ || anArgCase == "-PRSRANGE")
+ {
+ if (aLightCurr.IsNull()
+ || (aLightCurr->Type() != Graphic3d_TOLS_SPOT
+ && aLightCurr->Type() != Graphic3d_TOLS_POSITIONAL))
+ {
+ Message::SendFail() << "Syntax error at argument '" << anArg << "'";
+ return 1;
+ }
+
+ if (Handle(AIS_LightSource) aLightSource = findLightPrs (aLightCurr))
+ {
+ const bool toDisplay = Draw::ParseOnOffIterator (theArgsNb, theArgVec, anArgIt);
+ aLightSource->SetDisplayRange (toDisplay);
+ }
+ else
+ {
+ return 1;
+ }
+ }
+ else if (anArgCase == "-SHOWSIZE"
+ || anArgCase == "-PRSSIZE")
+ {
+ Standard_Real aSize = 0.0;
+ if ((anArgIt + 1) >= theArgsNb
+ || !Draw::ParseReal (theArgVec[anArgIt + 1], aSize)
+ || aSize <= 0.0)
+ {
+ Message::SendFail() << "Syntax error at argument '" << anArg << "'";
+ return 1;
+ }
+
+ ++anArgIt;
+ if (Handle(AIS_LightSource) aLightSource = findLightPrs (aLightCurr))
+ {
+ aLightSource->SetSize (aSize);
+ }
+ else
+ {
+ return 1;
+ }
+ }
else if (anArgCase.IsEqual ("-CASTSHADOW")
|| anArgCase.IsEqual ("-CASTSHADOWS")
|| anArgCase.IsEqual ("-SHADOWS"))
}
addLight (aLightNew, aLayer, isGlobal);
+
+ struct LightPrsSort
+ {
+ bool operator() (const Handle(AIS_LightSource)& theLeft,
+ const Handle(AIS_LightSource)& theRight)
+ {
+ return theLeft->Light()->GetId() < theRight->Light()->GetId();
+ }
+ };
+
+ AIS_ListOfInteractive aPrsList;
+ ViewerTest::GetAISContext()->DisplayedObjects (AIS_KindOfInteractive_LightSource, -1, aPrsList);
+ if (!aPrsList.IsEmpty())
+ {
+ // update light source presentations
+ std::vector<Handle(AIS_LightSource)> aLightPrsVec;
+ for (AIS_ListOfInteractive::Iterator aPrsIter (aPrsList); aPrsIter.More(); aPrsIter.Next())
+ {
+ if (Handle(AIS_LightSource) aLightPrs = Handle(AIS_LightSource)::DownCast (aPrsIter.Value()))
+ {
+ aLightPrsVec.push_back (aLightPrs);
+ }
+ }
+
+ // sort objects by id as AIS_InteractiveContext stores them in unordered map
+ std::sort (aLightPrsVec.begin(), aLightPrsVec.end(), LightPrsSort());
+
+ Standard_Integer aTopStack = 0;
+ for (std::vector<Handle(AIS_LightSource)>::iterator aPrsIter = aLightPrsVec.begin(); aPrsIter != aLightPrsVec.end(); ++aPrsIter)
+ {
+ Handle(AIS_LightSource) aLightPrs = *aPrsIter;
+ if (!aLightPrs->TransformPersistence().IsNull()
+ && aLightPrs->TransformPersistence()->IsTrihedronOr2d())
+ {
+ const Standard_Integer aPrsSize = (Standard_Integer )aLightPrs->Size();
+ aLightPrs->TransformPersistence()->SetOffset2d (Graphic3d_Vec2i (aTopStack + aPrsSize, aPrsSize));
+ aTopStack += aPrsSize + aPrsSize / 2;
+ }
+ ViewerTest::GetAISContext()->Redisplay (aLightPrs, false);
+ ViewerTest::GetAISContext()->SetTransformPersistence (aLightPrs, aLightPrs->TransformPersistence());
+ }
+ }
return 0;
}
"tool to manage light sources, without arguments shows list of lights."
"\n Main commands: "
"\n '-clear' to clear lights"
- "\n '-{def}aults' to load deafault lights"
+ "\n '-{def}aults' to load default lights"
"\n '-add' <type> to add any light source"
"\n where <type> is one of {amb}ient|directional|{spot}light|positional"
"\n 'change' <lightId> to edit light source with specified lightId"
"\n -{spotexp}onent value"
"\n -range value"
"\n -local|-global"
- "\n\n example: vlight -add positional -head 1 -pos 0 1 1 -color red"
+ "\n -name value"
+ "\n -display nameOfLight (display light source with specified nameOfLight or its name)"
+ "\n -showName {1|0} show/hide the name of light source; 1 by default"
+ "\n -showRange {1|0} show/hide the range of spot/positional light source; 1 by default"
+ "\n -prsZoomable {1|0} make light presentation zoomable/non-zoomable"
+ "\n -prsSize {Value} set light presentation size"
+ "\n\n example: vlight -add positional -head 1 -pos 0 1 1 -color red"
"\n example: vlight -change 0 -direction 0 -1 0 -linearAttenuation 0.2",
__FILE__, VLight, group);
theCommands.Add("vpbrenv",
024 colors
025 quadric
026 shadows
+027 light_source
--- /dev/null
+puts "================================="
+puts "0031704: Visualization - add an interactive object AIS_LightSource representing a light source"
+puts "================================="
+
+pload MODELING VISUALIZATION
+vclear
+vinit View1 -width 1280 -height 720
+vlight -clear
+vbackground -color GRAY
+vrenderparams -shadingModel PBR
+box b 10 10 10 30 30 30
+vdisplay b -dispMode 1
+vaspects b -material Brass
+vfit
+
+puts "=== Add light sources and display their presentations ==="
+vlight -add ambient -color WHITE -name AMBIENT -display
+vlight -add directional -dir 0 1 0 -name DIR -color GREEN -display
+vlight -add spotlight -pos 50 25 25 -dir -1 0 0 -intensity 1000000000 -name SPOT -color RED -display
+vlight -add positional -pos 25 25 50 -intensity 10000000000 -range 20 -name POSITIONAL -color BLUE -display
+
+vdump $imagedir/${casename}_def.png
+
+puts "=== Turn off light sources ==="
+set mouse_pick_amb {105 97}
+set mouse_pick_spot {897 508}
+set mouse_pick_pos {640 62}
+set mouse_pick_dir {330 536}
+vselect {*}$mouse_pick_amb
+vselect {*}$mouse_pick_spot
+vselect {*}$mouse_pick_pos
+vselect {*}$mouse_pick_dir
+vdump $imagedir/${casename}_off.png
+
+set aColor_spot [vreadpixel 796 454 rgb name]
+set aColor_pos [vreadpixel 630 177 rgb name]
+if { "$aColor_spot" != "LIGHTSALMON3" } { puts "Error: expected color near the light spot is LIGHTSALMON3" }
+if { "$aColor_pos" != "THISTLE4"} { puts "Error: expected color near the positional light is THISTLE4" }
+
+puts "=== Delete presentations of light sources ==="
+vremove AMBIENT DIR SPOT POSITIONAL
+
+puts "=== Display all light sources ==="
+vlight -change 0 -display
+vlight -change 1 -display
+vlight -change 2 -display -showRange 1
+vlight -change 3 -display -showRange 1
+vdump $imagedir/${casename}_on.png
+
+puts "=== Turn on light sources ==="
+vselect {*}$mouse_pick_amb
+vselect {*}$mouse_pick_spot
+vselect {*}$mouse_pick_pos
+vselect {*}$mouse_pick_dir
+set aColor_spot [vreadpixel 796 454 rgb name]
+set aColor_pos [vreadpixel 630 177 rgb name]
+set aColor_dir [vreadpixel 453 453 rgb name]
+if { "$aColor_spot" != "CORAL" } { puts "Error: expected color near the light spot is CORAL" }
+if { "$aColor_pos" != "LIGHTSLATEBLUE"} { puts "Error: expected color near the positional light is LIGHTSLATEBLUE" }
+if { "$aColor_dir" != "BURLYWOOD3" } { puts "Error: expected color near the directional light is BURLYWOOD3" }
+
+#vlight -clear
+#vdump $imagedir/${casename}_cleared.png
--- /dev/null
+puts "================================="
+puts "0031704: Visualization - add an interactive object AIS_LightSource representing a light source"
+puts "================================="
+
+pload MODELING VISUALIZATION
+vclear
+vinit View1
+vlight -clear
+vbackground -color GRAY
+vrenderparams -shadingModel PHONG
+vlight -add ambient -COLOR WHITE -intensity 0.1
+box b 10 10 10 30 30 30
+vdisplay b -dispMode 1
+vaspects b -material Brass
+vfit
+
+puts "=== Check headlight option with spotlight ==="
+vlight -add spotlight -dir 0 0 -1 -head 1 -intensity 1000000000 -color GREEN -display aSpotlight
+set aColor1 [vreadpixel 200 200 rgb name]
+if { "$aColor1" != "GREEN" } { puts "Error: expected color near the light is GREEN" }
+vdump $imagedir/${casename}_spot.png
+
+puts "=== Check headlight option with positional light ==="
+vlight -remove 1
+vlight -add positional -head 1 -color RED -display aPosLight
+set aColor2 [vreadpixel 200 200 rgb name]
+if { "$aColor2" != "RED" } { puts "Error: expected color near the light is RED" }
+vdump $imagedir/${casename}_pos.png
--- /dev/null
+puts "==================================================="
+puts "0031704: Visualization - add an interactive object AIS_LightSource representing a light source"
+puts "==================================================="
+
+pload MODELING VISUALIZATION
+vclear
+vinit View1
+vlight -clear
+vbackground -color GRAY
+vrenderparams -shadingModel PHONG
+vlight -add ambient -COLOR WHITE -intensity 0.1
+box b 0 0 0 30 30 30
+vdisplay b -dispMode 1
+vsetmaterial b Brass
+vfit
+vlight -add spotlight -pos 15 -10 15 -dir 0 1 0 -name aSpotLight -color RED -display
+
+puts "=== Attach manipulator ==="
+vmanipulator m -attach aSpotLight -adjustPosition location
+vdump $imagedir/${casename}_manip.png
+
+puts "=== Test manipulator - rotation ==="
+vmanipulator m -followRotation 1
+
+set mouse_pick_rotate {128 231}
+set mouse_drag_rotate {98 200}
+
+vmoveto {*}$mouse_pick_rotate
+vselect {*}$mouse_pick_rotate
+vmanipulator m -startTransform {*}$mouse_pick_rotate
+vmanipulator m -transform {*}$mouse_drag_rotate
+vmanipulator m -stopTransform
+vselect 0 0
+vmoveto {*}$mouse_drag_rotate
+vdump $imagedir/${casename}_rot.png
+
+puts "=== Test manipulator - translation ==="
+set mouse_pick_translate {87 315}
+set mouse_drag_translate {167 358}
+
+vmoveto {*}$mouse_pick_translate
+vselect {*}$mouse_pick_translate
+vmanipulator m -startTransform {*}$mouse_pick_translate
+vmanipulator m -transform {*}$mouse_drag_translate
+vmanipulator m -stopTransform
+vselect 0 0
+vmoveto {*}$mouse_drag_translate
+vmanipulator m -detach
+vremove aSpotLight
+vdump $imagedir/${casename}_trans.png
vlight -clear
vlight -add ambient
vlight -add directional -dir -0.577 -0.577 -0.577 -head 1
-vlight -add directional -dir 0.577, 0.577, 0.577 -head 0
+vlight -add directional -dir 0.577 0.577 0.577 -head 0
vrenderparams -raytrace -raydepth 3 -shadows on -reflections -fsaa