1 // Created on: 2020-09-07
2 // Created by: Maria KRYLOVA
3 // Copyright (c) 2020 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15 
16 #include <AIS_LightSource.hxx>
17 
18 #include <AIS_InteractiveContext.hxx>
19 #include <gp_Quaternion.hxx>
20 #include <Graphic3d_ArrayOfPoints.hxx>
21 #include <Graphic3d_ArrayOfPolylines.hxx>
22 #include <Graphic3d_ArrayOfSegments.hxx>
23 #include <Graphic3d_ArrayOfTriangles.hxx>
24 #include <Graphic3d_CView.hxx>
25 #include <Graphic3d_Group.hxx>
26 #include <Prs3d_ArrowAspect.hxx>
27 #include <Prs3d_PointAspect.hxx>
28 #include <Prs3d_Text.hxx>
29 #include <Prs3d_ToolCylinder.hxx>
30 #include <Prs3d_ToolSphere.hxx>
31 #include <Select3D_SensitivePoint.hxx>
32 #include <Select3D_SensitiveSphere.hxx>
33 #include <V3d_View.hxx>
34 
IMPLEMENT_STANDARD_RTTIEXT(AIS_LightSource,AIS_InteractiveObject)35 IMPLEMENT_STANDARD_RTTIEXT(AIS_LightSource, AIS_InteractiveObject)
36 IMPLEMENT_STANDARD_RTTIEXT(AIS_LightSourceOwner, SelectMgr_EntityOwner)
37 
38 // =======================================================================
39 // function : AIS_LightSourceOwner
40 // purpose  :
41 // =======================================================================
42 AIS_LightSourceOwner::AIS_LightSourceOwner (const Handle(AIS_LightSource)& theObject,
43                                             Standard_Integer thePriority)
44 : SelectMgr_EntityOwner ((const Handle(SelectMgr_SelectableObject)&)theObject, thePriority)
45 {
46   //
47 }
48 
49 // =======================================================================
50 // function : HandleMouseClick
51 // purpose  :
52 // =======================================================================
HandleMouseClick(const Graphic3d_Vec2i &,Aspect_VKeyMouse theKey,Aspect_VKeyFlags theFlags,bool)53 Standard_Boolean AIS_LightSourceOwner::HandleMouseClick (const Graphic3d_Vec2i& ,
54                                                          Aspect_VKeyMouse theKey,
55                                                          Aspect_VKeyFlags theFlags,
56                                                          bool )
57 {
58   AIS_LightSource* aLightSource = dynamic_cast<AIS_LightSource*>(mySelectable);
59   if (aLightSource != NULL
60    && aLightSource->ToSwitchOnClick()
61    && theKey == Aspect_VKeyMouse_LeftButton
62    && theFlags == Aspect_VKeyFlags_NONE)
63   {
64     aLightSource->Light()->SetEnabled (!aLightSource->Light()->IsEnabled());
65     aLightSource->updateLightAspects();
66     return true;
67   }
68   return false;
69 }
70 
71 //=======================================================================
72 //function : HilightWithColor
73 //purpose  :
74 //=======================================================================
HilightWithColor(const Handle (PrsMgr_PresentationManager)& thePM,const Handle (Prs3d_Drawer)& theStyle,const Standard_Integer theMode)75 void AIS_LightSourceOwner::HilightWithColor (const Handle(PrsMgr_PresentationManager)& thePM,
76                                              const Handle(Prs3d_Drawer)& theStyle,
77                                              const Standard_Integer theMode)
78 {
79   Handle(AIS_LightSource) aLightSource = Handle(AIS_LightSource)::DownCast (mySelectable);
80   if (aLightSource.IsNull())
81   {
82     return;
83   }
84 
85   if (aLightSource->Light()->Type() == Graphic3d_TypeOfLightSource_Directional && aLightSource->myIsDraggable)
86   {
87     Handle(Prs3d_Presentation) aPrs = aLightSource->GetHilightPresentation (thePM);
88     const Graphic3d_ZLayerId aZLayer = theStyle->ZLayer() != -1
89                                      ? theStyle->ZLayer()
90                                      : (thePM->IsImmediateModeOn() ? Graphic3d_ZLayerId_Top : aLightSource->ZLayer());
91     aPrs->Clear();
92     if (aPrs->GetZLayer() != aZLayer)
93     {
94       aPrs->SetZLayer (aZLayer);
95     }
96     Handle(Graphic3d_ArrayOfPoints) aPoints = new Graphic3d_ArrayOfPoints (1);
97     const gp_Pnt aDetPnt = aLightSource->mySensSphere->LastDetectedPoint();
98     if (aDetPnt.X() == RealLast())
99     {
100       return;
101     }
102     aPoints->AddVertex (aDetPnt);
103     Handle(Graphic3d_Group) aGroup = aPrs->NewGroup();
104     const Handle(Prs3d_PointAspect) aPointAspect = new Prs3d_PointAspect (Aspect_TOM_O_POINT, theStyle->Color(), 3.0f);
105     aGroup->SetGroupPrimitivesAspect (aPointAspect->Aspect());
106     aGroup->AddPrimitiveArray (aPoints);
107 
108     const Standard_Real aRadius = aLightSource->Size() * 0.5;
109     const Standard_Integer aNbPnts = int (aLightSource->ArcSize() * 180 / (M_PI * aRadius));
110     TColgp_Array1OfPnt aCircPoints (0, aNbPnts);
111     const gp_Dir aDirNorm (gp_Vec (gp::Origin(), aDetPnt));
112     gp_Dir aDirNormToPln (gp::DY());
113     if (!gp::DX().IsParallel (aDirNorm, Precision::Angular()))
114     {
115       aDirNormToPln = gp::DX().Crossed (aDirNorm);
116     }
117     for (Standard_Integer aStep = 0; aStep < aNbPnts; ++aStep)
118     {
119       aCircPoints.SetValue (aStep, (aDetPnt.Rotated (gp_Ax1 (gp::Origin(), aDirNormToPln), M_PI / 90 * (aStep - aNbPnts / 2))));
120     }
121 
122     Handle(Graphic3d_Group) aCircGroup = aPrs->NewGroup();
123     Handle(Graphic3d_ArrayOfPolylines) aPolylines = new Graphic3d_ArrayOfPolylines (aNbPnts * 2, 2);
124     aPolylines->AddBound (aNbPnts);
125 
126     for (Standard_Integer anIdx = 0; anIdx < aNbPnts; ++anIdx)
127     {
128       aPolylines->AddVertex (aCircPoints.Value (anIdx).Rotated (gp_Ax1 (gp::Origin(), aDirNorm), M_PI / 2));
129     }
130     aPolylines->AddBound (aNbPnts);
131     for (Standard_Integer anIdx = 0; anIdx < aNbPnts; ++anIdx)
132     {
133       aPolylines->AddVertex (aCircPoints.Value (anIdx));
134     }
135     aCircGroup->AddPrimitiveArray (aPolylines, Standard_False);
136     aCircGroup->SetGroupPrimitivesAspect (theStyle->ArrowAspect()->Aspect());
137     if (thePM->IsImmediateModeOn())
138     {
139       thePM->AddToImmediateList (aPrs);
140     }
141     else
142     {
143       aPrs->Display();
144     }
145   }
146   else
147   {
148     base_type::HilightWithColor (thePM, theStyle, theMode);;
149   }
150 }
151 
152 //=======================================================================
153 //function : IsForcedHilight
154 //purpose  :
155 //=======================================================================
IsForcedHilight() const156 Standard_Boolean AIS_LightSourceOwner::IsForcedHilight() const
157 {
158   Handle(AIS_LightSource) aLightSource = Handle(AIS_LightSource)::DownCast (mySelectable);
159   if (aLightSource.IsNull())
160   {
161     return Standard_False;
162   }
163   if (aLightSource->Light()->Type() == Graphic3d_TypeOfLightSource_Directional)
164   {
165     return Standard_True;
166   }
167   return Standard_False;
168 }
169 
170 // =======================================================================
171 // function : Constructor
172 // purpose  :
173 // =======================================================================
AIS_LightSource(const Handle (Graphic3d_CLight)& theLight)174 AIS_LightSource::AIS_LightSource (const Handle(Graphic3d_CLight)& theLight)
175 : myLightSource (theLight),
176   myCodirMarkerType (Aspect_TOM_X),
177   myOpposMarkerType (Aspect_TOM_O_POINT),
178   mySize (50),
179   myNbArrows (5),
180   myNbSplitsQuadric (theLight->Type() == Graphic3d_TypeOfLightSource_Ambient ? 10 : 30),
181   myNbSplitsArrow (20),
182   mySensSphereArcSize (25),
183   myIsZoomable (theLight->Type() == Graphic3d_TypeOfLightSource_Positional
184              || theLight->Type() == Graphic3d_TypeOfLightSource_Spot),
185   myIsDraggable (theLight->Type() == Graphic3d_TypeOfLightSource_Directional),
186   myToDisplayName (true),
187   myToDisplayRange (true),
188   myToSwitchOnClick (true)
189 {
190   myMarkerTypes[0] = Aspect_TOM_O_X;
191   myMarkerTypes[1] = Aspect_TOM_O_POINT;
192 
193   myInfiniteState = true;
194 
195   const Quantity_Color aColor = theLight->Color();
196   myDrawer->SetPointAspect (new Prs3d_PointAspect (myMarkerTypes[1], aColor, 3.0f));
197   myDisabledMarkerAspect = new Graphic3d_AspectMarker3d (Aspect_TOM_EMPTY, aColor, 3.0f);
198 
199   Graphic3d_MaterialAspect aMat (Graphic3d_NameOfMaterial_UserDefined);
200   aMat.SetColor (aColor);
201   myDrawer->SetArrowAspect (new Prs3d_ArrowAspect());
202   myDrawer->ArrowAspect()->SetColor (aColor);
203   myDrawer->ArrowAspect()->Aspect()->SetShadingModel (Graphic3d_TypeOfShadingModel_Unlit);
204   myDrawer->ArrowAspect()->Aspect()->ChangeFrontMaterial() = aMat;
205   myDrawer->ArrowAspect()->Aspect()->SetMarkerType (Aspect_TOM_EMPTY);
206   myDrawer->ArrowAspect()->Aspect()->SetMarkerScale (2.0f);
207   myArrowLineAspectShadow = new Graphic3d_AspectLine3d (Quantity_NOC_BLACK, Aspect_TOL_SOLID,
208                                                         theLight->Type() != Graphic3d_TypeOfLightSource_Ambient ? 3.0f : 1.0f);
209 
210   myDrawer->SetupOwnShadingAspect();
211   myDrawer->ShadingAspect()->SetColor (aColor);
212   myDrawer->ShadingAspect()->SetMaterial (aMat);
213   myDrawer->ShadingAspect()->SetTransparency (0.5f);
214   myDrawer->ShadingAspect()->Aspect()->SetShadingModel (Graphic3d_TypeOfShadingModel_Unlit);
215 
216   myDrawer->SetTextAspect (new Prs3d_TextAspect());
217   myDrawer->TextAspect()->Aspect()->SetDisplayType (Aspect_TODT_SHADOW);
218   myDrawer->TextAspect()->Aspect()->SetColorSubTitle (Quantity_NOC_BLACK);
219   myDrawer->TextAspect()->SetHorizontalJustification (Graphic3d_HTA_LEFT);
220   myDrawer->TextAspect()->SetVerticalJustification (Graphic3d_VTA_TOPFIRSTLINE);
221 
222   updateLightTransformPersistence();
223 
224   myDrawer->SetDisplayMode (0);
225   myDynHilightDrawer = new Prs3d_Drawer();
226   myDynHilightDrawer->Link (myDrawer);
227   myDynHilightDrawer->SetDisplayMode (1);
228   myDynHilightDrawer->SetColor (Quantity_NOC_CYAN1);
229 
230   if (!myTransformPersistence.IsNull()
231     && myTransformPersistence->IsTrihedronOr2d())
232   {
233     myDrawer->SetZLayer (Graphic3d_ZLayerId_Topmost);
234     myDynHilightDrawer->SetZLayer (Graphic3d_ZLayerId_Topmost);
235     myDrawer->TextAspect()->SetHorizontalJustification (Graphic3d_HTA_CENTER);
236     myDrawer->TextAspect()->SetVerticalJustification (Graphic3d_VTA_TOP);
237   }
238 }
239 
240 //=======================================================================
241 //function : ProcessDragging
242 //purpose  :
243 //=======================================================================
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)244 Standard_Boolean AIS_LightSource::ProcessDragging (const Handle(AIS_InteractiveContext)& theCtx,
245                                                    const Handle(V3d_View)& theView,
246                                                    const Handle(SelectMgr_EntityOwner)& theOwner,
247                                                    const Graphic3d_Vec2i& theDragFrom,
248                                                    const Graphic3d_Vec2i& theDragTo,
249                                                    const AIS_DragAction theAction)
250 {
251   if (Light()->Type() != Graphic3d_TypeOfLightSource_Directional)
252   {
253     return Standard_False;
254   }
255 
256   switch (theAction)
257   {
258     case AIS_DragAction_Start:
259     {
260       myLocTrsfStart = LocalTransformation();
261       return Standard_True;
262     }
263     case AIS_DragAction_Update:
264     {
265       mySensSphere->ResetLastDetectedPoint();
266       SetLocalTransformation (myLocTrsfStart);
267       theCtx->MainSelector()->Pick (theDragFrom.x(), theDragFrom.y(), theView);
268       gp_Pnt aStartPosition = mySensSphere->LastDetectedPoint();
269 
270       mySensSphere->ResetLastDetectedPoint();
271       theCtx->MainSelector()->Pick (theDragTo.x(), theDragTo.y(), theView);
272       gp_Pnt aCurrPosition = mySensSphere->LastDetectedPoint();
273       if (aCurrPosition.X() != RealLast()
274        && aStartPosition.Distance (aCurrPosition) > Precision::Confusion())
275       {
276         gp_Quaternion aQRot;
277         aQRot.SetRotation (gp_Vec (gp_Pnt (0, 0, 0), aStartPosition), gp_Vec (gp_Pnt (0, 0, 0), aCurrPosition));
278         gp_Trsf aTrsf;
279         aTrsf.SetRotation (aQRot);
280         SetLocalTransformation (myLocTrsfStart * aTrsf);
281         const Standard_Integer aHiMod = HasHilightMode() ? HilightMode() : 0;
282         theOwner->UpdateHighlightTrsf (theCtx->CurrentViewer(), theCtx->MainPrsMgr(), aHiMod);
283       }
284       return Standard_True;
285     }
286     case AIS_DragAction_Abort:
287     {
288       return Standard_True;
289     }
290     case AIS_DragAction_Stop:
291     {
292       GetHilightPresentation (theCtx->MainPrsMgr())->Clear();
293       break;
294     }
295   }
296   return Standard_False;
297 }
298 
299 // =======================================================================
300 // function : updateLightAspects
301 // purpose  :
302 // =======================================================================
updateLightAspects()303 void AIS_LightSource::updateLightAspects()
304 {
305   const Quantity_Color aBaseColor = myLightSource->Color();
306   const Quantity_Color aDimColor (aBaseColor.Rgb() * 0.3f);
307   const Quantity_Color aColor = myLightSource->IsEnabled() ? aBaseColor : aDimColor;
308   myDrawer->PointAspect()->SetColor (aColor);
309   myDrawer->PointAspect()->Aspect()->SetMarkerType (MarkerType (myLightSource->IsEnabled()));
310   myDrawer->PointAspect()->Aspect()->SetMarkerImage(MarkerImage(myLightSource->IsEnabled()));
311 
312   myDisabledMarkerAspect->SetColor (aColor);
313   myDisabledMarkerAspect->SetMarkerScale(myDrawer->PointAspect()->Aspect()->MarkerScale());
314   myDisabledMarkerAspect->SetMarkerType (myLightSource->IsEnabled() ? Aspect_TOM_EMPTY : MarkerType (false));
315   myDisabledMarkerAspect->SetMarkerImage(MarkerImage (false));
316 
317   myDrawer->ShadingAspect()->SetColor (aColor);
318   myDrawer->ArrowAspect()  ->SetColor (aColor);
319   myDrawer->ArrowAspect()->Aspect()->ChangeFrontMaterial().SetColor (aColor);
320 
321   if (myLightSource->Type() == Graphic3d_TypeOfLightSource_Directional)
322   {
323     const Standard_Real anAngleTol = 2.0 * M_PI / 180.0;
324     Aspect_TypeOfMarker aDirMark = Aspect_TOM_EMPTY;
325     if (myLightSource->IsEnabled()
326      && myLightSource->IsHeadlight()
327      && myLightSource->Direction().IsParallel (gp::DZ(), anAngleTol))
328     {
329       aDirMark = myLightSource->Direction().IsOpposite (-gp::DZ(), anAngleTol) ? myOpposMarkerType : myCodirMarkerType;
330     }
331     myDrawer->ArrowAspect()->Aspect()->SetMarkerType (aDirMark);
332   }
333   SynchronizeAspects();
334 }
335 
336 // =======================================================================
337 // function : updateLightTransformPersistence
338 // purpose  :
339 // =======================================================================
updateLightTransformPersistence()340 void AIS_LightSource::updateLightTransformPersistence()
341 {
342   Handle(Graphic3d_TransformPers) aTrsfPers = myTransformPersistence;
343   switch (myLightSource->Type())
344   {
345     case Graphic3d_TypeOfLightSource_Ambient:
346     {
347       if (!myIsZoomable)
348       {
349         if (aTrsfPers.IsNull() || !aTrsfPers->IsTrihedronOr2d())
350         {
351           aTrsfPers = new Graphic3d_TransformPers (Graphic3d_TMF_TriedronPers, Aspect_TOTP_LEFT_UPPER, Graphic3d_Vec2i(50));
352         }
353       }
354       else
355       {
356         aTrsfPers.Nullify();
357       }
358       break;
359     }
360     case Graphic3d_TypeOfLightSource_Directional:
361     {
362       Graphic3d_TransModeFlags aMode = myLightSource->IsHeadlight() ? Graphic3d_TMF_2d : Graphic3d_TMF_TriedronPers;
363       if (myIsZoomable)
364       {
365         aMode = myLightSource->IsHeadlight() ? Graphic3d_TMF_CameraPers : Graphic3d_TMF_None;
366       }
367       if (aMode != Graphic3d_TMF_None)
368       {
369         if (aTrsfPers.IsNull() || aTrsfPers->Mode() != aMode)
370         {
371           if (aMode == Graphic3d_TMF_CameraPers)
372           {
373             aTrsfPers = new Graphic3d_TransformPers (Graphic3d_TMF_CameraPers);
374           }
375           else
376           {
377             aTrsfPers = new Graphic3d_TransformPers (aMode, Aspect_TOTP_LEFT_UPPER, Graphic3d_Vec2i(50));
378           }
379         }
380       }
381       else
382       {
383         aTrsfPers.Nullify();
384       }
385       break;
386     }
387     case Graphic3d_TypeOfLightSource_Positional:
388     case Graphic3d_TypeOfLightSource_Spot:
389     {
390       Graphic3d_TransModeFlags aMode = myLightSource->IsHeadlight()
391                                      ? Graphic3d_TMF_CameraPers
392                                      : (!myIsZoomable ? Graphic3d_TMF_ZoomPers : Graphic3d_TMF_None);
393       if (aMode != Graphic3d_TMF_None)
394       {
395         if (aTrsfPers.IsNull() || aTrsfPers->Mode() != aMode)
396         {
397           if (aMode == Graphic3d_TMF_CameraPers)
398           {
399             aTrsfPers = new Graphic3d_TransformPers (Graphic3d_TMF_CameraPers);
400           }
401           else
402           {
403             aTrsfPers = new Graphic3d_TransformPers (aMode, myLightSource->Position());
404           }
405         }
406         if (aMode == Graphic3d_TMF_ZoomPers)
407         {
408           aTrsfPers->SetAnchorPoint (myLightSource->Position());
409         }
410       }
411       else
412       {
413         aTrsfPers.Nullify();
414       }
415       break;
416     }
417   }
418 
419   SetTransformPersistence (aTrsfPers);
420 }
421 
422 // =======================================================================
423 // function : updateLightLocalTransformation
424 // purpose  :
425 // =======================================================================
updateLightLocalTransformation()426 void AIS_LightSource::updateLightLocalTransformation()
427 {
428   myLocalTransformation.Nullify();
429   switch (myLightSource->Type())
430   {
431     case Graphic3d_TypeOfLightSource_Ambient:
432     {
433       if (myIsZoomable)
434       {
435         gp_Trsf aTrsf;
436         aTrsf.SetTranslation (gp::Origin(), myLightSource->Position());
437         myLocalTransformation = new TopLoc_Datum3D (aTrsf);
438       }
439       break;
440     }
441     case Graphic3d_TypeOfLightSource_Directional:
442     {
443       const gp_Pnt aLightPos = (myIsZoomable && !myLightSource->IsHeadlight())
444                              ? myLightSource->DisplayPosition()
445                              : gp::Origin();
446       gp_Trsf aTrsf;
447       const gp_Ax2 anAx2 (aLightPos, -myLightSource->Direction());
448       aTrsf.SetTransformation (anAx2, gp_Ax3());
449       myLocalTransformation = new TopLoc_Datum3D (aTrsf);
450       break;
451     }
452     case Graphic3d_TypeOfLightSource_Positional:
453     {
454       if (myIsZoomable)
455       {
456         gp_Trsf aTrsf;
457         aTrsf.SetTranslation (gp::Origin(), myLightSource->Position());
458         myLocalTransformation = new TopLoc_Datum3D (aTrsf);
459       }
460       break;
461     }
462     case Graphic3d_TypeOfLightSource_Spot:
463     {
464       gp_Trsf aTrsf;
465       const gp_Ax2 anAx2 (myIsZoomable ? myLightSource->Position() : gp::Origin(), -myLightSource->Direction());
466       aTrsf.SetTransformation (anAx2, gp_Ax3());
467       myLocalTransformation = new TopLoc_Datum3D (aTrsf);
468       break;
469     }
470   }
471   UpdateTransformation();
472 }
473 
474 // =======================================================================
475 // function : setLocalTransformation
476 // purpose  :
477 // =======================================================================
setLocalTransformation(const Handle (TopLoc_Datum3D)& theTrsf)478 void AIS_LightSource::setLocalTransformation (const Handle(TopLoc_Datum3D)& theTrsf)
479 {
480   const gp_Trsf aTrsf = !theTrsf.IsNull() ? theTrsf->Transformation() : gp_Trsf();
481   switch (myLightSource->Type())
482   {
483     case Graphic3d_TypeOfLightSource_Ambient:
484     {
485       break;
486     }
487     case Graphic3d_TypeOfLightSource_Directional:
488     {
489       gp_Dir aNewDir = (-gp::DZ()).Transformed (aTrsf);
490       myLightSource->SetDirection (aNewDir);
491       if (myIsZoomable)
492       {
493         gp_Pnt aNewPos = gp::Origin().Transformed (aTrsf);
494         myLightSource->SetDisplayPosition (aNewPos);
495       }
496       break;
497     }
498     case Graphic3d_TypeOfLightSource_Positional:
499     {
500       gp_Pnt aNewPos = gp::Origin().Transformed (aTrsf);
501       myLightSource->SetPosition (aNewPos);
502       break;
503     }
504     case Graphic3d_TypeOfLightSource_Spot:
505     {
506       gp_Pnt aNewPos = gp::Origin().Transformed (aTrsf);
507       myLightSource->SetPosition (aNewPos);
508 
509       gp_Dir aNewDir = (-gp::DZ()).Transformed (aTrsf);
510       myLightSource->SetDirection (aNewDir);
511       break;
512     }
513   }
514 
515   base_type::setLocalTransformation (new TopLoc_Datum3D (aTrsf));
516 
517   updateLightAspects();
518   updateLightTransformPersistence();
519 }
520 
521 // =======================================================================
522 // function : Compute
523 // purpose  :
524 // =======================================================================
Compute(const Handle (PrsMgr_PresentationManager)&,const Handle (Prs3d_Presentation)& thePrs,const Standard_Integer theMode)525 void AIS_LightSource::Compute (const Handle(PrsMgr_PresentationManager)& ,
526                                const Handle(Prs3d_Presentation)& thePrs,
527                                const Standard_Integer theMode)
528 {
529   thePrs->SetInfiniteState (myInfiniteState);
530   if (theMode != 0
531    && theMode != 1)
532   {
533     return;
534   }
535 
536   if (theMode == 0)
537   {
538     updateLightAspects();
539     updateLightTransformPersistence();
540     updateLightLocalTransformation();
541   }
542 
543   switch (myLightSource->Type())
544   {
545     case Graphic3d_TypeOfLightSource_Ambient:     computeAmbient    (thePrs, theMode); break;
546     case Graphic3d_TypeOfLightSource_Directional: computeDirectional(thePrs, theMode); break;
547     case Graphic3d_TypeOfLightSource_Positional:  computePositional (thePrs, theMode); break;
548     case Graphic3d_TypeOfLightSource_Spot:        computeSpot       (thePrs, theMode); break;
549   }
550 
551   if (myToDisplayName)
552   {
553     TCollection_AsciiString aPrefix = !myTransformPersistence.IsNull()
554                                     && myTransformPersistence->IsTrihedronOr2d()
555                                     ? "\n" : "   ";
556     TCollection_AsciiString aName = aPrefix + myLightSource->Name();
557     Prs3d_Text::Draw (thePrs->NewGroup(), myDrawer->TextAspect(), aName, gp::Origin());
558   }
559 }
560 
561 // =======================================================================
562 // function : computeAmbient
563 // purpose  :
564 // =======================================================================
computeAmbient(const Handle (Prs3d_Presentation)& thePrs,const Standard_Integer theMode)565 void AIS_LightSource::computeAmbient (const Handle(Prs3d_Presentation)& thePrs,
566                                       const Standard_Integer theMode)
567 {
568   const gp_XYZ aLightPos = gp::Origin().XYZ();
569   if (theMode == 0)
570   {
571     Handle(Graphic3d_ArrayOfTriangles) aSphereArray = Prs3d_ToolSphere::Create (mySize * 0.25, myNbSplitsQuadric, myNbSplitsQuadric, gp_Trsf());
572     Handle(Graphic3d_Group) aSphereGroup = thePrs->NewGroup();
573     aSphereGroup->SetClosed (true);
574     aSphereGroup->SetGroupPrimitivesAspect (myDrawer->ShadingAspect()->Aspect());
575     aSphereGroup->AddPrimitiveArray (aSphereArray);
576   }
577   if (theMode == 0
578    || theMode == 1)
579   {
580     const Standard_Real aLen = mySize * 0.25;
581     const Standard_Integer aNbArrows = 6;
582     const gp_Dir aDirList[6] = { -gp::DX(), gp::DX(), -gp::DY(), gp::DY(), -gp::DZ(), gp::DZ() };
583 
584     const Prs3d_ToolCylinder aCylTool (mySize * 0.1, 0.0, mySize * 0.2, myNbSplitsArrow, myNbSplitsArrow);
585     Handle(Graphic3d_ArrayOfTriangles) aTrisArray = new Graphic3d_ArrayOfTriangles (aNbArrows * aCylTool.VerticesNb(),
586                                                                                     aNbArrows * aCylTool.TrianglesNb() * 3,
587                                                                                     Graphic3d_ArrayFlags_VertexNormal);
588     Handle(Graphic3d_ArrayOfSegments) aLineArray = new Graphic3d_ArrayOfSegments (aNbArrows * 2);
589     for (Standard_Integer anArrIter = 0; anArrIter < aNbArrows; ++anArrIter)
590     {
591       const gp_Dir& aDir = aDirList[anArrIter];
592       const gp_XYZ  aPnt = aLightPos + aDir.XYZ() * aLen;
593       if (!aLineArray.IsNull())
594       {
595         aLineArray->AddVertex (aPnt + aDir.XYZ() * aLen * 0.5);
596         aLineArray->AddVertex (aPnt + aDir.XYZ() * aLen * 1.5);
597       }
598       if (!aTrisArray.IsNull())
599       {
600         const gp_Ax3 aSystem (aPnt + aDir.XYZ() * aLen, -aDir);
601         gp_Trsf aTrsfCone;
602         aTrsfCone.SetTransformation (aSystem, gp_Ax3());
603         aCylTool.FillArray (aTrisArray, aTrsfCone);
604       }
605     }
606 
607     if (!aLineArray.IsNull())
608     {
609       Handle(Graphic3d_Group) aDirGroupShadow = thePrs->NewGroup();
610       aDirGroupShadow->SetGroupPrimitivesAspect (myArrowLineAspectShadow);
611       aDirGroupShadow->AddPrimitiveArray (aLineArray);
612     }
613     if (!aTrisArray.IsNull())
614     {
615       Handle(Graphic3d_Group) anArrowGroup = thePrs->NewGroup();
616       anArrowGroup->SetClosed (true);
617       anArrowGroup->SetGroupPrimitivesAspect (myDrawer->ArrowAspect()->Aspect());
618       anArrowGroup->AddPrimitiveArray (aTrisArray);
619     }
620   }
621 
622   {
623     Handle(Graphic3d_ArrayOfPoints) aPoints = new Graphic3d_ArrayOfPoints (1);
624     aPoints->AddVertex (aLightPos);
625     Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
626     aGroup->SetGroupPrimitivesAspect (theMode == 1 ? myDrawer->PointAspect()->Aspect() : myDisabledMarkerAspect);
627     aGroup->AddPrimitiveArray (aPoints);
628   }
629 }
630 
631 // =======================================================================
632 // function : computeDirectional
633 // purpose  :
634 // =======================================================================
computeDirectional(const Handle (Prs3d_Presentation)& thePrs,const Standard_Integer theMode)635 void AIS_LightSource::computeDirectional (const Handle(Prs3d_Presentation)& thePrs,
636                                           const Standard_Integer theMode)
637 {
638   const Standard_Real aDistance = mySize * 0.5;
639   const Standard_Real aStep = aDistance * 0.5;
640 
641   // light source direction is set to local transformation
642   const gp_Dir aLightDir = -gp::DZ();
643   const gp_XYZ aLightPos = -aStep * aLightDir.XYZ();
644 
645   Standard_Integer aNbArrows = 1;
646   if      (myNbArrows >= 9) { aNbArrows = 9; }
647   else if (myNbArrows >= 5) { aNbArrows = 5; }
648   else if (myNbArrows >= 3) { aNbArrows = 3; }
649   TColgp_Array1OfPnt aPoints (1, aNbArrows);
650   {
651     const gp_Ax2 anAxes (gp::Origin(), aLightDir);
652     const gp_XYZ aDY = anAxes.YDirection().XYZ() * aStep;
653     const gp_XYZ aDX = anAxes.XDirection().XYZ() * aStep;
654     const gp_XYZ aDXY = aDX + aDY;
655     switch (aNbArrows)
656     {
657       case 9:
658       {
659         aPoints.SetValue (6, aLightPos + aDY);
660         aPoints.SetValue (7, aLightPos + aDX);
661         aPoints.SetValue (8, aLightPos - aDY);
662         aPoints.SetValue (9, aLightPos - aDX);
663       }
664       Standard_FALLTHROUGH
665       case 5:
666       {
667         aPoints.SetValue (4, aLightPos - aDY + aDX);
668         aPoints.SetValue (5, aLightPos + aDY - aDX);
669       }
670       Standard_FALLTHROUGH
671       case 3:
672       {
673         aPoints.SetValue (2, aLightPos + aDXY);
674         aPoints.SetValue (3, aLightPos - aDXY);
675       }
676       Standard_FALLTHROUGH
677       case 1:
678       {
679         aPoints.SetValue (1, aLightPos);
680         break;
681       }
682     }
683   }
684 
685   const Prs3d_ToolCylinder aCylTool (aDistance * 0.1, 0.0, aDistance * 0.2, myNbSplitsArrow, myNbSplitsArrow);
686   Handle(Graphic3d_ArrayOfTriangles) aTrisArray;
687   if (theMode == 0)
688   {
689     aTrisArray = new Graphic3d_ArrayOfTriangles (aNbArrows * aCylTool.VerticesNb(),
690                                                  aNbArrows * aCylTool.TrianglesNb() * 3,
691                                                  Graphic3d_ArrayFlags_VertexNormal);
692   }
693   Handle(Graphic3d_ArrayOfPoints) aPntArray = new Graphic3d_ArrayOfPoints (aNbArrows);
694   Handle(Graphic3d_ArrayOfSegments) aLineArray = new Graphic3d_ArrayOfSegments (aNbArrows * 2);
695   for (Standard_Integer aPntIter = aPoints.Lower(); aPntIter <= aPoints.Upper(); ++aPntIter)
696   {
697     const gp_Pnt aPnt = aPoints.Value (aPntIter);
698     if (!aPntArray.IsNull())
699     {
700       aPntArray->AddVertex (aPnt);
701     }
702     if (!aLineArray.IsNull())
703     {
704       aLineArray->AddVertex (aPnt);
705       aLineArray->AddVertex (gp_Pnt (aPnt.XYZ() + aLightDir.XYZ() * aDistance));
706     }
707     if (!aTrisArray.IsNull())
708     {
709       const gp_Ax3 aSystem (aPnt.XYZ() + aLightDir.XYZ() * aDistance, aLightDir);
710       gp_Trsf aTrsfCone;
711       aTrsfCone.SetTransformation (aSystem, gp_Ax3());
712       aCylTool.FillArray (aTrisArray, aTrsfCone);
713     }
714   }
715 
716   if (!aLineArray.IsNull() && theMode == 0)
717   {
718     Handle(Graphic3d_Group) aDirGroupShadow = thePrs->NewGroup();
719     aDirGroupShadow->SetGroupPrimitivesAspect (myArrowLineAspectShadow);
720     aDirGroupShadow->AddPrimitiveArray (aLineArray);
721   }
722   if (!aLineArray.IsNull())
723   {
724     Handle(Graphic3d_Group) aDirGroup = thePrs->NewGroup();
725     aDirGroup->SetGroupPrimitivesAspect (myDrawer->ArrowAspect()->Aspect());
726     aDirGroup->AddPrimitiveArray (aLineArray);
727   }
728   if (!aTrisArray.IsNull())
729   {
730     Handle(Graphic3d_Group) anArrowGroup = thePrs->NewGroup();
731     anArrowGroup->SetClosed (true);
732     anArrowGroup->SetGroupPrimitivesAspect (myDrawer->ArrowAspect()->Aspect());
733     anArrowGroup->AddPrimitiveArray (aTrisArray);
734   }
735   if (!aPntArray.IsNull())
736   {
737     Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
738     aGroup->SetGroupPrimitivesAspect (myDrawer->ArrowAspect()->Aspect());
739     aGroup->AddPrimitiveArray (aPntArray);
740   }
741   {
742     Handle(Graphic3d_ArrayOfPoints) aPntArray2 = new Graphic3d_ArrayOfPoints (1);
743     aPntArray2->AddVertex (aLightPos);
744     Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
745     aGroup->SetGroupPrimitivesAspect (myDisabledMarkerAspect);
746     aGroup->AddPrimitiveArray (aPntArray2);
747   }
748 }
749 
750 // =======================================================================
751 // function : computePositional
752 // purpose  :
753 // =======================================================================
computePositional(const Handle (Prs3d_Presentation)& thePrs,const Standard_Integer theMode)754 void AIS_LightSource::computePositional (const Handle(Prs3d_Presentation)& thePrs,
755                                          const Standard_Integer theMode)
756 {
757   // light source position is set to local transformation
758   const gp_XYZ aLightPos = gp::Origin().XYZ();
759   const Standard_Real aRadius = (myIsZoomable && myLightSource->HasRange()) ? myLightSource->Range() : 0.0;
760   if (theMode == 0
761    && aRadius > 0.0
762    && myToDisplayRange)
763   {
764     Handle(Graphic3d_ArrayOfTriangles) aPosRangeArray = Prs3d_ToolSphere::Create (aRadius, myNbSplitsQuadric, myNbSplitsQuadric, gp_Trsf());
765     Handle(Graphic3d_Group) aRangeGroup = thePrs->NewGroup();
766     aRangeGroup->SetClosed (true);
767     aRangeGroup->SetGroupPrimitivesAspect (myDrawer->ShadingAspect()->Aspect());
768     aRangeGroup->AddPrimitiveArray (aPosRangeArray);
769   }
770   {
771     Handle(Graphic3d_ArrayOfPoints) aPoints = new Graphic3d_ArrayOfPoints (1);
772     aPoints->AddVertex (aLightPos);
773     Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
774     aGroup->SetGroupPrimitivesAspect (myDrawer->PointAspect()->Aspect());
775     aGroup->AddPrimitiveArray (aPoints);
776   }
777 }
778 
779 // =======================================================================
780 // function : computeSpot
781 // purpose  :
782 // =======================================================================
computeSpot(const Handle (Prs3d_Presentation)& thePrs,const Standard_Integer theMode)783 void AIS_LightSource::computeSpot (const Handle(Prs3d_Presentation)& thePrs,
784                                    const Standard_Integer theMode)
785 {
786   // light source position and direction are set to local transformation
787   const gp_Dir aLightDir = -gp::DZ();
788   const gp_XYZ aLightPos = gp::Origin().XYZ();
789   const Standard_Real aDistance = (myIsZoomable && myLightSource->HasRange()) ? myLightSource->Range() : mySize;
790   {
791     Handle(Graphic3d_ArrayOfPoints) aPoints = new Graphic3d_ArrayOfPoints (1);
792     aPoints->AddVertex (aLightPos);
793 
794     Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
795     aGroup->SetGroupPrimitivesAspect (myDrawer->PointAspect()->Aspect());
796     aGroup->AddPrimitiveArray (aPoints);
797   }
798 
799   {
800     Handle(Graphic3d_ArrayOfSegments) aDirArray = new Graphic3d_ArrayOfSegments (2);
801     aDirArray->AddVertex (aLightPos);
802     aDirArray->AddVertex (gp_Pnt (aLightPos + aLightDir.XYZ() * aDistance));
803 
804     Handle(Graphic3d_Group) aDirGroupShadow = thePrs->NewGroup();
805     aDirGroupShadow->SetClosed (true);
806     aDirGroupShadow->SetGroupPrimitivesAspect (myArrowLineAspectShadow);
807     aDirGroupShadow->AddPrimitiveArray (aDirArray);
808 
809     Handle(Graphic3d_Group) aDirGroup = thePrs->NewGroup();
810     aDirGroup->SetClosed (true);
811     aDirGroup->SetGroupPrimitivesAspect (myDrawer->ArrowAspect()->Aspect());
812     aDirGroup->AddPrimitiveArray (aDirArray);
813   }
814 
815   if (theMode == 0
816    && myToDisplayRange)
817   {
818     const Standard_ShortReal aHalfAngle = myLightSource->Angle() / 2.0f;
819     const Standard_Real aRadius = aDistance * Tan (aHalfAngle);
820     gp_Ax3  aSystem (aLightPos + aLightDir.XYZ() * aDistance, -aLightDir);
821     gp_Trsf aTrsfCone;
822     aTrsfCone.SetTransformation (aSystem, gp_Ax3());
823     Handle(Graphic3d_ArrayOfTriangles) aSpotRangeArray = Prs3d_ToolCylinder::Create (aRadius, 0.0, aDistance,
824                                                                                      myNbSplitsQuadric, myNbSplitsQuadric, aTrsfCone);
825 
826     Handle(Graphic3d_Group) aRangeGroup = thePrs->NewGroup();
827     aRangeGroup->SetClosed (true);
828     aRangeGroup->SetGroupPrimitivesAspect (myDrawer->ShadingAspect()->Aspect());
829     aRangeGroup->AddPrimitiveArray (aSpotRangeArray);
830   }
831 }
832 
833 // =======================================================================
834 // function : ComputeSelection
835 // purpose  :
836 // =======================================================================
ComputeSelection(const Handle (SelectMgr_Selection)& theSel,const Standard_Integer theMode)837 void AIS_LightSource::ComputeSelection (const Handle(SelectMgr_Selection)& theSel,
838                                         const Standard_Integer theMode)
839 {
840   if (theMode != 0)
841   {
842     return;
843   }
844 
845   Handle(AIS_LightSourceOwner) anEntityOwner = new AIS_LightSourceOwner (this, 15);
846   {
847     if (myLightSource->Type() == Graphic3d_TypeOfLightSource_Directional)
848     {
849       mySensSphere = new Select3D_SensitiveSphere (anEntityOwner, gp::Origin(), mySize * 0.5);
850       theSel->Add (mySensSphere);
851     }
852 
853     Handle(Select3D_SensitivePoint) aSensPosition = new Select3D_SensitivePoint (anEntityOwner, gp::Origin());
854     aSensPosition->SetSensitivityFactor (12);
855     if (!myTransformPersistence.IsNull()
856       && myTransformPersistence->IsTrihedronOr2d())
857     {
858       aSensPosition->SetSensitivityFactor (Max (12, Standard_Integer (mySize * 0.5)));
859     }
860     theSel->Add (aSensPosition);
861   }
862 }
863