0032306: Draw Harness, ViewerTest - move window message processing to TKService
[occt.git] / src / AIS / AIS_LightSource.cxx
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 <Graphic3d_ArrayOfPoints.hxx>
20 #include <Graphic3d_ArrayOfSegments.hxx>
21 #include <Graphic3d_ArrayOfTriangles.hxx>
22 #include <Graphic3d_CView.hxx>
23 #include <Graphic3d_Group.hxx>
24 #include <Prs3d_ArrowAspect.hxx>
25 #include <Prs3d_PointAspect.hxx>
26 #include <Prs3d_Text.hxx>
27 #include <Prs3d_ToolCylinder.hxx>
28 #include <Prs3d_ToolSphere.hxx>
29 #include <Select3D_SensitivePoint.hxx>
30 #include <V3d_View.hxx>
31
32 IMPLEMENT_STANDARD_RTTIEXT(AIS_LightSource, AIS_InteractiveObject)
33 IMPLEMENT_STANDARD_RTTIEXT(AIS_LightSourceOwner, SelectMgr_EntityOwner)
34
35 // =======================================================================
36 // function : AIS_LightSourceOwner
37 // purpose  :
38 // =======================================================================
39 AIS_LightSourceOwner::AIS_LightSourceOwner (const Handle(AIS_LightSource)& theObject,
40                                             Standard_Integer thePriority)
41 : SelectMgr_EntityOwner ((const Handle(SelectMgr_SelectableObject)&)theObject, thePriority)
42 {
43   //
44 }
45
46 // =======================================================================
47 // function : HandleMouseClick
48 // purpose  :
49 // =======================================================================
50 Standard_Boolean AIS_LightSourceOwner::HandleMouseClick (const Graphic3d_Vec2i& ,
51                                                          Aspect_VKeyMouse theKey,
52                                                          Aspect_VKeyFlags theFlags,
53                                                          bool )
54 {
55   AIS_LightSource* aLightSource = dynamic_cast<AIS_LightSource*>(mySelectable);
56   if (aLightSource != NULL
57    && aLightSource->ToSwitchOnClick()
58    && theKey == Aspect_VKeyMouse_LeftButton
59    && theFlags == Aspect_VKeyFlags_NONE)
60   {
61     aLightSource->Light()->SetEnabled (!aLightSource->Light()->IsEnabled());
62     aLightSource->updateLightAspects();
63     return true;
64   }
65   return false;
66 }
67
68 // =======================================================================
69 // function : Constructor
70 // purpose  :
71 // =======================================================================
72 AIS_LightSource::AIS_LightSource (const Handle(Graphic3d_CLight)& theLight)
73 : myLightSource (theLight),
74   myCodirMarkerType (Aspect_TOM_X),
75   myOpposMarkerType (Aspect_TOM_O_POINT),
76   mySize (50),
77   myNbArrows (5),
78   myNbSplitsQuadric (theLight->Type() == Graphic3d_TOLS_AMBIENT ? 10 : 30),
79   myNbSplitsArrow (20),
80   myIsZoomable (theLight->Type() == Graphic3d_TOLS_POSITIONAL
81              || theLight->Type() == Graphic3d_TOLS_SPOT),
82   myToDisplayName (true),
83   myToDisplayRange (true),
84   myToSwitchOnClick (true)
85 {
86   myMarkerTypes[0] = Aspect_TOM_O_X;
87   myMarkerTypes[1] = Aspect_TOM_O_POINT;
88
89   myInfiniteState = true;
90
91   const Quantity_Color aColor = theLight->Color();
92   myDrawer->SetPointAspect (new Prs3d_PointAspect (myMarkerTypes[1], aColor, 3.0f));
93   myDisabledMarkerAspect = new Graphic3d_AspectMarker3d (Aspect_TOM_EMPTY, aColor, 3.0f);
94
95   Graphic3d_MaterialAspect aMat (Graphic3d_NameOfMaterial_UserDefined);
96   aMat.SetColor (aColor);
97   myDrawer->SetArrowAspect (new Prs3d_ArrowAspect());
98   myDrawer->ArrowAspect()->SetColor (aColor);
99   myDrawer->ArrowAspect()->Aspect()->SetShadingModel (Graphic3d_TOSM_UNLIT);
100   myDrawer->ArrowAspect()->Aspect()->ChangeFrontMaterial() = aMat;
101   myDrawer->ArrowAspect()->Aspect()->SetMarkerType (Aspect_TOM_EMPTY);
102   myDrawer->ArrowAspect()->Aspect()->SetMarkerScale (2.0f);
103   myArrowLineAspectShadow = new Graphic3d_AspectLine3d (Quantity_NOC_BLACK, Aspect_TOL_SOLID,
104                                                         theLight->Type() != Graphic3d_TOLS_AMBIENT ? 3.0f : 1.0f);
105
106   myDrawer->SetupOwnShadingAspect();
107   myDrawer->ShadingAspect()->SetColor (aColor);
108   myDrawer->ShadingAspect()->SetMaterial (aMat);
109   myDrawer->ShadingAspect()->SetTransparency (0.5f);
110   myDrawer->ShadingAspect()->Aspect()->SetShadingModel (Graphic3d_TOSM_UNLIT);
111
112   myDrawer->SetTextAspect (new Prs3d_TextAspect());
113   myDrawer->TextAspect()->Aspect()->SetDisplayType (Aspect_TODT_SHADOW);
114   myDrawer->TextAspect()->Aspect()->SetColorSubTitle (Quantity_NOC_BLACK);
115   myDrawer->TextAspect()->SetHorizontalJustification (Graphic3d_HTA_LEFT);
116   myDrawer->TextAspect()->SetVerticalJustification (Graphic3d_VTA_TOPFIRSTLINE);
117
118   updateLightTransformPersistence();
119
120   myDrawer->SetDisplayMode (0);
121   myDynHilightDrawer = new Prs3d_Drawer();
122   myDynHilightDrawer->Link (myDrawer);
123   myDynHilightDrawer->SetDisplayMode (1);
124   myDynHilightDrawer->SetColor (Quantity_NOC_CYAN1);
125
126   if (!myTransformPersistence.IsNull()
127     && myTransformPersistence->IsTrihedronOr2d())
128   {
129     myDrawer->SetZLayer (Graphic3d_ZLayerId_Topmost);
130     myDynHilightDrawer->SetZLayer (Graphic3d_ZLayerId_Topmost);
131     myDrawer->TextAspect()->SetHorizontalJustification (Graphic3d_HTA_CENTER);
132     myDrawer->TextAspect()->SetVerticalJustification (Graphic3d_VTA_TOP);
133   }
134 }
135
136 // =======================================================================
137 // function : updateLightAspects
138 // purpose  :
139 // =======================================================================
140 void AIS_LightSource::updateLightAspects()
141 {
142   const Quantity_Color aBaseColor = myLightSource->Color();
143   const Quantity_Color aDimColor (aBaseColor.Rgb() * 0.3f);
144   const Quantity_Color aColor = myLightSource->IsEnabled() ? aBaseColor : aDimColor;
145   myDrawer->PointAspect()->SetColor (aColor);
146   myDrawer->PointAspect()->Aspect()->SetMarkerType (MarkerType (myLightSource->IsEnabled()));
147   myDrawer->PointAspect()->Aspect()->SetMarkerImage(MarkerImage(myLightSource->IsEnabled()));
148
149   myDisabledMarkerAspect->SetColor (aColor);
150   myDisabledMarkerAspect->SetMarkerScale(myDrawer->PointAspect()->Aspect()->MarkerScale());
151   myDisabledMarkerAspect->SetMarkerType (myLightSource->IsEnabled() ? Aspect_TOM_EMPTY : MarkerType (false));
152   myDisabledMarkerAspect->SetMarkerImage(MarkerImage (false));
153
154   myDrawer->ShadingAspect()->SetColor (aColor);
155   myDrawer->ArrowAspect()  ->SetColor (aColor);
156   myDrawer->ArrowAspect()->Aspect()->ChangeFrontMaterial().SetColor (aColor);
157
158   if (myLightSource->Type() == Graphic3d_TOLS_DIRECTIONAL)
159   {
160     const Standard_Real anAngleTol = 2.0 * M_PI / 180.0;
161     Aspect_TypeOfMarker aDirMark = Aspect_TOM_EMPTY;
162     if (myLightSource->IsEnabled()
163      && myLightSource->IsHeadlight()
164      && myLightSource->Direction().IsParallel (gp::DZ(), anAngleTol))
165     {
166       aDirMark = myLightSource->Direction().IsOpposite (-gp::DZ(), anAngleTol) ? myOpposMarkerType : myCodirMarkerType;
167     }
168     myDrawer->ArrowAspect()->Aspect()->SetMarkerType (aDirMark);
169   }
170   SynchronizeAspects();
171 }
172
173 // =======================================================================
174 // function : updateLightTransformPersistence
175 // purpose  :
176 // =======================================================================
177 void AIS_LightSource::updateLightTransformPersistence()
178 {
179   Handle(Graphic3d_TransformPers) aTrsfPers = myTransformPersistence;
180   switch (myLightSource->Type())
181   {
182     case Graphic3d_TOLS_AMBIENT:
183     {
184       if (!myIsZoomable)
185       {
186         if (aTrsfPers.IsNull() || !aTrsfPers->IsTrihedronOr2d())
187         {
188           aTrsfPers = new Graphic3d_TransformPers (Graphic3d_TMF_TriedronPers, Aspect_TOTP_LEFT_UPPER, Graphic3d_Vec2i(50));
189         }
190       }
191       else
192       {
193         aTrsfPers.Nullify();
194       }
195       break;
196     }
197     case Graphic3d_TOLS_DIRECTIONAL:
198     {
199       Graphic3d_TransModeFlags aMode = myLightSource->IsHeadlight() ? Graphic3d_TMF_2d : Graphic3d_TMF_TriedronPers;
200       if (myIsZoomable)
201       {
202         aMode = myLightSource->IsHeadlight() ? Graphic3d_TMF_CameraPers : Graphic3d_TMF_None;
203       }
204       if (aMode != Graphic3d_TMF_None)
205       {
206         if (aTrsfPers.IsNull() || aTrsfPers->Mode() != aMode)
207         {
208           if (aMode == Graphic3d_TMF_CameraPers)
209           {
210             aTrsfPers = new Graphic3d_TransformPers (Graphic3d_TMF_CameraPers);
211           }
212           else
213           {
214             aTrsfPers = new Graphic3d_TransformPers (aMode, Aspect_TOTP_LEFT_UPPER, Graphic3d_Vec2i(50));
215           }
216         }
217       }
218       else
219       {
220         aTrsfPers.Nullify();
221       }
222       break;
223     }
224     case Graphic3d_TOLS_POSITIONAL:
225     case Graphic3d_TOLS_SPOT:
226     {
227       Graphic3d_TransModeFlags aMode = myLightSource->IsHeadlight()
228                                      ? Graphic3d_TMF_CameraPers
229                                      : (!myIsZoomable ? Graphic3d_TMF_ZoomPers : Graphic3d_TMF_None);
230       if (aMode != Graphic3d_TMF_None)
231       {
232         if (aTrsfPers.IsNull() || aTrsfPers->Mode() != aMode)
233         {
234           if (aMode == Graphic3d_TMF_CameraPers)
235           {
236             aTrsfPers = new Graphic3d_TransformPers (Graphic3d_TMF_CameraPers);
237           }
238           else
239           {
240             aTrsfPers = new Graphic3d_TransformPers (aMode, myLightSource->Position());
241           }
242         }
243         if (aMode == Graphic3d_TMF_ZoomPers)
244         {
245           aTrsfPers->SetAnchorPoint (myLightSource->Position());
246         }
247       }
248       else
249       {
250         aTrsfPers.Nullify();
251       }
252       break;
253     }
254   }
255
256   SetTransformPersistence (aTrsfPers);
257 }
258
259 // =======================================================================
260 // function : updateLightLocalTransformation
261 // purpose  :
262 // =======================================================================
263 void AIS_LightSource::updateLightLocalTransformation()
264 {
265   myLocalTransformation.Nullify();
266   switch (myLightSource->Type())
267   {
268     case Graphic3d_TOLS_AMBIENT:
269     {
270       if (myIsZoomable)
271       {
272         gp_Trsf aTrsf;
273         aTrsf.SetTranslation (gp::Origin(), myLightSource->Position());
274         myLocalTransformation = new TopLoc_Datum3D (aTrsf);
275       }
276       break;
277     }
278     case Graphic3d_TOLS_DIRECTIONAL:
279     {
280       const gp_Pnt aLightPos = (myIsZoomable && !myLightSource->IsHeadlight())
281                              ? myLightSource->DisplayPosition()
282                              : gp::Origin();
283       gp_Trsf aTrsf;
284       const gp_Ax2 anAx2 (aLightPos, -myLightSource->Direction());
285       aTrsf.SetTransformation (anAx2, gp_Ax3());
286       myLocalTransformation = new TopLoc_Datum3D (aTrsf);
287       break;
288     }
289     case Graphic3d_TOLS_POSITIONAL:
290     {
291       if (myIsZoomable)
292       {
293         gp_Trsf aTrsf;
294         aTrsf.SetTranslation (gp::Origin(), myLightSource->Position());
295         myLocalTransformation = new TopLoc_Datum3D (aTrsf);
296       }
297       break;
298     }
299     case Graphic3d_TOLS_SPOT:
300     {
301       gp_Trsf aTrsf;
302       const gp_Ax2 anAx2 (myIsZoomable ? myLightSource->Position() : gp::Origin(), -myLightSource->Direction());
303       aTrsf.SetTransformation (anAx2, gp_Ax3());
304       myLocalTransformation = new TopLoc_Datum3D (aTrsf);
305       break;
306     }
307   }
308   UpdateTransformation();
309 }
310
311 // =======================================================================
312 // function : setLocalTransformation
313 // purpose  :
314 // =======================================================================
315 void AIS_LightSource::setLocalTransformation (const Handle(TopLoc_Datum3D)& theTrsf)
316 {
317   const gp_Trsf aTrsf = theTrsf->Transformation();
318   switch (myLightSource->Type())
319   {
320     case Graphic3d_TOLS_AMBIENT:
321     {
322       break;
323     }
324     case Graphic3d_TOLS_DIRECTIONAL:
325     {
326       gp_Dir aNewDir = (-gp::DZ()).Transformed (aTrsf);
327       myLightSource->SetDirection (aNewDir);
328       if (myIsZoomable)
329       {
330         gp_Pnt aNewPos = gp::Origin().Transformed (aTrsf);
331         myLightSource->SetDisplayPosition (aNewPos);
332       }
333       break;
334     }
335     case Graphic3d_TOLS_POSITIONAL:
336     {
337       gp_Pnt aNewPos = gp::Origin().Transformed (aTrsf);
338       myLightSource->SetPosition (aNewPos);
339       break;
340     }
341     case Graphic3d_TOLS_SPOT:
342     {
343       gp_Pnt aNewPos = gp::Origin().Transformed (aTrsf);
344       myLightSource->SetPosition (aNewPos);
345
346       gp_Dir aNewDir = (-gp::DZ()).Transformed (aTrsf);
347       myLightSource->SetDirection (aNewDir);
348       break;
349     }
350   }
351
352   base_type::setLocalTransformation (new TopLoc_Datum3D (aTrsf));
353
354   updateLightAspects();
355   updateLightTransformPersistence();
356 }
357
358 // =======================================================================
359 // function : Compute
360 // purpose  :
361 // =======================================================================
362 void AIS_LightSource::Compute (const Handle(PrsMgr_PresentationManager)& ,
363                                const Handle(Prs3d_Presentation)& thePrs,
364                                const Standard_Integer theMode)
365 {
366   thePrs->SetInfiniteState (myInfiniteState);
367   if (theMode != 0
368    && theMode != 1)
369   {
370     return;
371   }
372
373   if (theMode == 0)
374   {
375     updateLightAspects();
376     updateLightTransformPersistence();
377     updateLightLocalTransformation();
378   }
379
380   switch (myLightSource->Type())
381   {
382     case Graphic3d_TOLS_AMBIENT:     computeAmbient    (thePrs, theMode); break;
383     case Graphic3d_TOLS_DIRECTIONAL: computeDirectional(thePrs, theMode); break;
384     case Graphic3d_TOLS_POSITIONAL:  computePositional (thePrs, theMode); break;
385     case Graphic3d_TOLS_SPOT:        computeSpot       (thePrs, theMode); break;
386   }
387
388   if (myToDisplayName)
389   {
390     TCollection_AsciiString aPrefix = !myTransformPersistence.IsNull()
391                                     && myTransformPersistence->IsTrihedronOr2d()
392                                     ? "\n" : "   ";
393     TCollection_AsciiString aName = aPrefix + myLightSource->Name();
394     Prs3d_Text::Draw (thePrs->NewGroup(), myDrawer->TextAspect(), aName, gp::Origin());
395   }
396 }
397
398 // =======================================================================
399 // function : computeAmbient
400 // purpose  :
401 // =======================================================================
402 void AIS_LightSource::computeAmbient (const Handle(Prs3d_Presentation)& thePrs,
403                                       const Standard_Integer theMode)
404 {
405   const gp_XYZ aLightPos = gp::Origin().XYZ();
406   if (theMode == 0)
407   {
408     Handle(Graphic3d_ArrayOfTriangles) aSphereArray = Prs3d_ToolSphere::Create (mySize * 0.25, myNbSplitsQuadric, myNbSplitsQuadric, gp_Trsf());
409     Handle(Graphic3d_Group) aSphereGroup = thePrs->NewGroup();
410     aSphereGroup->SetClosed (true);
411     aSphereGroup->SetGroupPrimitivesAspect (myDrawer->ShadingAspect()->Aspect());
412     aSphereGroup->AddPrimitiveArray (aSphereArray);
413   }
414   if (theMode == 0
415    || theMode == 1)
416   {
417     const Standard_Real aLen = mySize * 0.25;
418     const Standard_Integer aNbArrows = 6;
419     const gp_Dir aDirList[6] = { -gp::DX(), gp::DX(), -gp::DY(), gp::DY(), -gp::DZ(), gp::DZ() };
420
421     const Prs3d_ToolCylinder aCylTool (mySize * 0.1, 0.0, mySize * 0.2, myNbSplitsArrow, myNbSplitsArrow);
422     Handle(Graphic3d_ArrayOfTriangles) aTrisArray = new Graphic3d_ArrayOfTriangles (aNbArrows * aCylTool.VerticesNb(),
423                                                                                     aNbArrows * aCylTool.TrianglesNb() * 3,
424                                                                                     Graphic3d_ArrayFlags_VertexNormal);
425     Handle(Graphic3d_ArrayOfSegments) aLineArray = new Graphic3d_ArrayOfSegments (aNbArrows * 2);
426     for (Standard_Integer anArrIter = 0; anArrIter < aNbArrows; ++anArrIter)
427     {
428       const gp_Dir& aDir = aDirList[anArrIter];
429       const gp_XYZ  aPnt = aLightPos + aDir.XYZ() * aLen;
430       if (!aLineArray.IsNull())
431       {
432         aLineArray->AddVertex (aPnt + aDir.XYZ() * aLen * 0.5);
433         aLineArray->AddVertex (aPnt + aDir.XYZ() * aLen * 1.5);
434       }
435       if (!aTrisArray.IsNull())
436       {
437         const gp_Ax3 aSystem (aPnt + aDir.XYZ() * aLen, -aDir);
438         gp_Trsf aTrsfCone;
439         aTrsfCone.SetTransformation (aSystem, gp_Ax3());
440         aCylTool.FillArray (aTrisArray, aTrsfCone);
441       }
442     }
443
444     if (!aLineArray.IsNull())
445     {
446       Handle(Graphic3d_Group) aDirGroupShadow = thePrs->NewGroup();
447       aDirGroupShadow->SetGroupPrimitivesAspect (myArrowLineAspectShadow);
448       aDirGroupShadow->AddPrimitiveArray (aLineArray);
449     }
450     if (!aTrisArray.IsNull())
451     {
452       Handle(Graphic3d_Group) anArrowGroup = thePrs->NewGroup();
453       anArrowGroup->SetClosed (true);
454       anArrowGroup->SetGroupPrimitivesAspect (myDrawer->ArrowAspect()->Aspect());
455       anArrowGroup->AddPrimitiveArray (aTrisArray);
456     }
457   }
458
459   {
460     Handle(Graphic3d_ArrayOfPoints) aPoints = new Graphic3d_ArrayOfPoints (1);
461     aPoints->AddVertex (aLightPos);
462     Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
463     aGroup->SetGroupPrimitivesAspect (theMode == 1 ? myDrawer->PointAspect()->Aspect() : myDisabledMarkerAspect);
464     aGroup->AddPrimitiveArray (aPoints);
465   }
466 }
467
468 // =======================================================================
469 // function : computeDirectional
470 // purpose  :
471 // =======================================================================
472 void AIS_LightSource::computeDirectional (const Handle(Prs3d_Presentation)& thePrs,
473                                           const Standard_Integer theMode)
474 {
475   const Standard_Real aDistance = mySize * 0.5;
476   const Standard_Real aStep = aDistance * 0.5;
477
478   // light source direction is set to local transformation
479   const gp_Dir aLightDir = -gp::DZ();
480   const gp_XYZ aLightPos = -aStep * aLightDir.XYZ();
481
482   Standard_Integer aNbArrows = 1;
483   if      (myNbArrows >= 9) { aNbArrows = 9; }
484   else if (myNbArrows >= 5) { aNbArrows = 5; }
485   else if (myNbArrows >= 3) { aNbArrows = 3; }
486   TColgp_Array1OfPnt aPoints (1, aNbArrows);
487   {
488     const gp_Ax2 anAxes (gp::Origin(), aLightDir);
489     const gp_XYZ aDY = anAxes.YDirection().XYZ() * aStep;
490     const gp_XYZ aDX = anAxes.XDirection().XYZ() * aStep;
491     const gp_XYZ aDXY = aDX + aDY;
492     switch (aNbArrows)
493     {
494       case 9:
495       {
496         aPoints.SetValue (6, aLightPos + aDY);
497         aPoints.SetValue (7, aLightPos + aDX);
498         aPoints.SetValue (8, aLightPos - aDY);
499         aPoints.SetValue (9, aLightPos - aDX);
500       }
501       Standard_FALLTHROUGH
502       case 5:
503       {
504         aPoints.SetValue (4, aLightPos - aDY + aDX);
505         aPoints.SetValue (5, aLightPos + aDY - aDX);
506       }
507       Standard_FALLTHROUGH
508       case 3:
509       {
510         aPoints.SetValue (2, aLightPos + aDXY);
511         aPoints.SetValue (3, aLightPos - aDXY);
512       }
513       Standard_FALLTHROUGH
514       case 1:
515       {
516         aPoints.SetValue (1, aLightPos);
517         break;
518       }
519     }
520   }
521
522   const Prs3d_ToolCylinder aCylTool (aDistance * 0.1, 0.0, aDistance * 0.2, myNbSplitsArrow, myNbSplitsArrow);
523   Handle(Graphic3d_ArrayOfTriangles) aTrisArray;
524   if (theMode == 0)
525   {
526     aTrisArray = new Graphic3d_ArrayOfTriangles (aNbArrows * aCylTool.VerticesNb(),
527                                                  aNbArrows * aCylTool.TrianglesNb() * 3,
528                                                  Graphic3d_ArrayFlags_VertexNormal);
529   }
530   Handle(Graphic3d_ArrayOfPoints) aPntArray = new Graphic3d_ArrayOfPoints (aNbArrows);
531   Handle(Graphic3d_ArrayOfSegments) aLineArray = new Graphic3d_ArrayOfSegments (aNbArrows * 2);
532   for (Standard_Integer aPntIter = aPoints.Lower(); aPntIter <= aPoints.Upper(); ++aPntIter)
533   {
534     const gp_Pnt aPnt = aPoints.Value (aPntIter);
535     if (!aPntArray.IsNull())
536     {
537       aPntArray->AddVertex (aPnt);
538     }
539     if (!aLineArray.IsNull())
540     {
541       aLineArray->AddVertex (aPnt);
542       aLineArray->AddVertex (gp_Pnt (aPnt.XYZ() + aLightDir.XYZ() * aDistance));
543     }
544     if (!aTrisArray.IsNull())
545     {
546       const gp_Ax3 aSystem (aPnt.XYZ() + aLightDir.XYZ() * aDistance, aLightDir);
547       gp_Trsf aTrsfCone;
548       aTrsfCone.SetTransformation (aSystem, gp_Ax3());
549       aCylTool.FillArray (aTrisArray, aTrsfCone);
550     }
551   }
552
553   if (!aLineArray.IsNull() && theMode == 0)
554   {
555     Handle(Graphic3d_Group) aDirGroupShadow = thePrs->NewGroup();
556     aDirGroupShadow->SetGroupPrimitivesAspect (myArrowLineAspectShadow);
557     aDirGroupShadow->AddPrimitiveArray (aLineArray);
558   }
559   if (!aLineArray.IsNull())
560   {
561     Handle(Graphic3d_Group) aDirGroup = thePrs->NewGroup();
562     aDirGroup->SetGroupPrimitivesAspect (myDrawer->ArrowAspect()->Aspect());
563     aDirGroup->AddPrimitiveArray (aLineArray);
564   }
565   if (!aTrisArray.IsNull())
566   {
567     Handle(Graphic3d_Group) anArrowGroup = thePrs->NewGroup();
568     anArrowGroup->SetClosed (true);
569     anArrowGroup->SetGroupPrimitivesAspect (myDrawer->ArrowAspect()->Aspect());
570     anArrowGroup->AddPrimitiveArray (aTrisArray);
571   }
572   if (!aPntArray.IsNull())
573   {
574     Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
575     aGroup->SetGroupPrimitivesAspect (myDrawer->ArrowAspect()->Aspect());
576     aGroup->AddPrimitiveArray (aPntArray);
577   }
578   {
579     Handle(Graphic3d_ArrayOfPoints) aPntArray2 = new Graphic3d_ArrayOfPoints (1);
580     aPntArray2->AddVertex (aLightPos);
581     Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
582     aGroup->SetGroupPrimitivesAspect (myDisabledMarkerAspect);
583     aGroup->AddPrimitiveArray (aPntArray2);
584   }
585 }
586
587 // =======================================================================
588 // function : computePositional
589 // purpose  :
590 // =======================================================================
591 void AIS_LightSource::computePositional (const Handle(Prs3d_Presentation)& thePrs,
592                                          const Standard_Integer theMode)
593 {
594   // light source position is set to local transformation
595   const gp_XYZ aLightPos = gp::Origin().XYZ();
596   const Standard_Real aRadius = (myIsZoomable && myLightSource->HasRange()) ? myLightSource->Range() : 0.0;
597   if (theMode == 0
598    && aRadius > 0.0
599    && myToDisplayRange)
600   {
601     Handle(Graphic3d_ArrayOfTriangles) aPosRangeArray = Prs3d_ToolSphere::Create (aRadius, myNbSplitsQuadric, myNbSplitsQuadric, gp_Trsf());
602     Handle(Graphic3d_Group) aRangeGroup = thePrs->NewGroup();
603     aRangeGroup->SetClosed (true);
604     aRangeGroup->SetGroupPrimitivesAspect (myDrawer->ShadingAspect()->Aspect());
605     aRangeGroup->AddPrimitiveArray (aPosRangeArray);
606   }
607   {
608     Handle(Graphic3d_ArrayOfPoints) aPoints = new Graphic3d_ArrayOfPoints (1);
609     aPoints->AddVertex (aLightPos);
610     Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
611     aGroup->SetGroupPrimitivesAspect (myDrawer->PointAspect()->Aspect());
612     aGroup->AddPrimitiveArray (aPoints);
613   }
614 }
615
616 // =======================================================================
617 // function : computeSpot
618 // purpose  :
619 // =======================================================================
620 void AIS_LightSource::computeSpot (const Handle(Prs3d_Presentation)& thePrs,
621                                    const Standard_Integer theMode)
622 {
623   // light source position and direction are set to local transformation
624   const gp_Dir aLightDir = -gp::DZ();
625   const gp_XYZ aLightPos = gp::Origin().XYZ();
626   const Standard_Real aDistance = (myIsZoomable && myLightSource->HasRange()) ? myLightSource->Range() : mySize;
627   {
628     Handle(Graphic3d_ArrayOfPoints) aPoints = new Graphic3d_ArrayOfPoints (1);
629     aPoints->AddVertex (aLightPos);
630
631     Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
632     aGroup->SetGroupPrimitivesAspect (myDrawer->PointAspect()->Aspect());
633     aGroup->AddPrimitiveArray (aPoints);
634   }
635
636   {
637     Handle(Graphic3d_ArrayOfSegments) aDirArray = new Graphic3d_ArrayOfSegments (2);
638     aDirArray->AddVertex (aLightPos);
639     aDirArray->AddVertex (gp_Pnt (aLightPos + aLightDir.XYZ() * aDistance));
640
641     Handle(Graphic3d_Group) aDirGroupShadow = thePrs->NewGroup();
642     aDirGroupShadow->SetClosed (true);
643     aDirGroupShadow->SetGroupPrimitivesAspect (myArrowLineAspectShadow);
644     aDirGroupShadow->AddPrimitiveArray (aDirArray);
645
646     Handle(Graphic3d_Group) aDirGroup = thePrs->NewGroup();
647     aDirGroup->SetClosed (true);
648     aDirGroup->SetGroupPrimitivesAspect (myDrawer->ArrowAspect()->Aspect());
649     aDirGroup->AddPrimitiveArray (aDirArray);
650   }
651
652   if (theMode == 0
653    && myToDisplayRange)
654   {
655     const Standard_ShortReal aHalfAngle = myLightSource->Angle() / 2.0f;
656     const Standard_Real aRadius = aDistance * Tan (aHalfAngle);
657     gp_Ax3  aSystem (aLightPos + aLightDir.XYZ() * aDistance, -aLightDir);
658     gp_Trsf aTrsfCone;
659     aTrsfCone.SetTransformation (aSystem, gp_Ax3());
660     Handle(Graphic3d_ArrayOfTriangles) aSpotRangeArray = Prs3d_ToolCylinder::Create (aRadius, 0.0, aDistance,
661                                                                                      myNbSplitsQuadric, myNbSplitsQuadric, aTrsfCone);
662
663     Handle(Graphic3d_Group) aRangeGroup = thePrs->NewGroup();
664     aRangeGroup->SetClosed (true);
665     aRangeGroup->SetGroupPrimitivesAspect (myDrawer->ShadingAspect()->Aspect());
666     aRangeGroup->AddPrimitiveArray (aSpotRangeArray);
667   }
668 }
669
670 // =======================================================================
671 // function : ComputeSelection
672 // purpose  :
673 // =======================================================================
674 void AIS_LightSource::ComputeSelection (const Handle(SelectMgr_Selection)& theSel,
675                                         const Standard_Integer theMode)
676 {
677   if (theMode != 0)
678   {
679     return;
680   }
681
682   Handle(AIS_LightSourceOwner) anEntityOwner = new AIS_LightSourceOwner (this, 15);
683   {
684     Handle(Select3D_SensitivePoint) aSensPosition = new Select3D_SensitivePoint (anEntityOwner, gp::Origin());
685     aSensPosition->SetSensitivityFactor (12);
686     if (!myTransformPersistence.IsNull()
687       && myTransformPersistence->IsTrihedronOr2d())
688     {
689       aSensPosition->SetSensitivityFactor (Max (12, Standard_Integer (mySize * 0.5)));
690     }
691     theSel->Add (aSensPosition);
692   }
693 }