0031313: Foundation Classes - Dump improvement for classes
[occt.git] / src / Graphic3d / Graphic3d_LightSet.cxx
1 // Copyright (c) 2017 OPEN CASCADE SAS
2 //
3 // This file is part of Open CASCADE Technology software library.
4 //
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
10 //
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
13
14 #include <Graphic3d_LightSet.hxx>
15
16 #include <NCollection_LocalArray.hxx>
17
18 IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_LightSet, Standard_Transient)
19
20 namespace
21 {
22   //! Suffixes identifying light source type.
23   static const char THE_LIGHT_KEY_LETTERS[Graphic3d_TypeOfLightSource_NB] =
24   {
25     'a', // Graphic3d_TOLS_AMBIENT
26     'd', // Graphic3d_TOLS_DIRECTIONAL
27     'p', // Graphic3d_TOLS_POSITIONAL
28     's'  // Graphic3d_TOLS_SPOT
29   };
30 }
31
32 // =======================================================================
33 // function : Graphic3d_LightSet
34 // purpose  :
35 // =======================================================================
36 Graphic3d_LightSet::Graphic3d_LightSet()
37 : myAmbient (0.0f, 0.0f, 0.0f, 0.0f),
38   myNbEnabled (0),
39   myRevision (1),
40   myCacheRevision (0)
41 {
42   memset (myLightTypes,        0, sizeof(myLightTypes));
43   memset (myLightTypesEnabled, 0, sizeof(myLightTypesEnabled));
44 }
45
46 // =======================================================================
47 // function : Add
48 // purpose  :
49 // =======================================================================
50 Standard_Boolean Graphic3d_LightSet::Add (const Handle(Graphic3d_CLight)& theLight)
51 {
52   if (theLight.IsNull())
53   {
54     throw Standard_ProgramError ("Graphic3d_LightSet::Add(), NULL argument");
55   }
56
57   const Standard_Integer anOldExtent = myLights.Extent();
58   const Standard_Integer anIndex     = myLights.Add (theLight, 0);
59   if (anIndex <= anOldExtent)
60   {
61     return Standard_False;
62   }
63
64   myLightTypes[theLight->Type()] += 1;
65   myLights.ChangeFromIndex (anIndex) = theLight->Revision();
66   ++myRevision;
67   return Standard_True;
68 }
69
70 // =======================================================================
71 // function : Remove
72 // purpose  :
73 // =======================================================================
74 Standard_Boolean Graphic3d_LightSet::Remove (const Handle(Graphic3d_CLight)& theLight)
75 {
76   const Standard_Integer anIndToRemove = myLights.FindIndex (theLight);
77   if (anIndToRemove <= 0)
78   {
79     return Standard_False;
80   }
81
82   ++myRevision;
83   myLights.RemoveFromIndex (anIndToRemove);
84   myLightTypes[theLight->Type()] -= 1;
85   return Standard_True;
86 }
87
88 // =======================================================================
89 // function : UpdateRevision
90 // purpose  :
91 // =======================================================================
92 Standard_Size Graphic3d_LightSet::UpdateRevision()
93 {
94   if (myCacheRevision == myRevision)
95   {
96     // check implicit updates of light sources
97     for (NCollection_IndexedDataMap<Handle(Graphic3d_CLight), Standard_Size>::Iterator aLightIter (myLights); aLightIter.More(); aLightIter.Next())
98     {
99       const Handle(Graphic3d_CLight)& aLight = aLightIter.Key();
100       if (aLightIter.Value() != aLight->Revision())
101       {
102         ++myRevision;
103         break;
104       }
105     }
106   }
107   if (myCacheRevision == myRevision)
108   {
109     return myRevision;
110   }
111
112   myCacheRevision = myRevision;
113   myAmbient.SetValues (0.0f, 0.0f, 0.0f, 0.0f);
114   memset (myLightTypesEnabled, 0, sizeof(myLightTypesEnabled));
115   NCollection_LocalArray<char, 32> aKeyLong (myLights.Extent() + 1);
116   Standard_Integer aLightLast = 0;
117   for (NCollection_IndexedDataMap<Handle(Graphic3d_CLight), Standard_Size>::Iterator aLightIter (myLights); aLightIter.More(); aLightIter.Next())
118   {
119     const Handle(Graphic3d_CLight)& aLight = aLightIter.Key();
120     aLightIter.ChangeValue() = aLight->Revision();
121     if (!aLight->IsEnabled())
122     {
123       continue;
124     }
125
126     myLightTypesEnabled[aLight->Type()] += 1;
127     if (aLight->Type() == Graphic3d_TOLS_AMBIENT)
128     {
129       myAmbient += aLight->PackedColor() * aLight->Intensity();
130     }
131     else
132     {
133       aKeyLong[aLightLast++] = THE_LIGHT_KEY_LETTERS[aLight->Type()];
134     }
135   }
136   aKeyLong[aLightLast] = '\0';
137   myAmbient.a() = 1.0f;
138   myNbEnabled = myLightTypesEnabled[Graphic3d_TOLS_DIRECTIONAL]
139               + myLightTypesEnabled[Graphic3d_TOLS_POSITIONAL]
140               + myLightTypesEnabled[Graphic3d_TOLS_SPOT];
141   myKeyEnabledLong  = aKeyLong;
142   myKeyEnabledShort = TCollection_AsciiString (myLightTypesEnabled[Graphic3d_TOLS_DIRECTIONAL] > 0 ? THE_LIGHT_KEY_LETTERS[Graphic3d_TOLS_DIRECTIONAL] : '\0')
143                     + TCollection_AsciiString (myLightTypesEnabled[Graphic3d_TOLS_POSITIONAL]  > 0 ? THE_LIGHT_KEY_LETTERS[Graphic3d_TOLS_POSITIONAL]  : '\0')
144                     + TCollection_AsciiString (myLightTypesEnabled[Graphic3d_TOLS_SPOT]        > 0 ? THE_LIGHT_KEY_LETTERS[Graphic3d_TOLS_SPOT]        : '\0');
145   return myRevision;
146 }