0031704: Visualization - add an interactive object AIS_LightSource representing a...
[occt.git] / src / Graphic3d / Graphic3d_CLight.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_CLight.hxx>
15
16 #include <Standard_Atomic.hxx>
17 #include <Standard_NotImplemented.hxx>
18 #include <Standard_OutOfRange.hxx>
19
20 IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_CLight, Standard_Transient)
21
22 namespace
23 {
24   static volatile Standard_Integer THE_LIGHT_COUNTER = 0;
25 }
26
27 // =======================================================================
28 // function : makeId
29 // purpose  :
30 // =======================================================================
31 void Graphic3d_CLight::makeId()
32 {
33   TCollection_AsciiString aTypeSuffix;
34   switch (myType)
35   {
36     case Graphic3d_TOLS_AMBIENT:     aTypeSuffix = "amb"; break;
37     case Graphic3d_TOLS_DIRECTIONAL: aTypeSuffix = "dir"; break;
38     case Graphic3d_TOLS_POSITIONAL:  aTypeSuffix = "pos"; break;
39     case Graphic3d_TOLS_SPOT:        aTypeSuffix = "spot"; break;
40   }
41
42   myId = TCollection_AsciiString ("Graphic3d_CLight_") + aTypeSuffix
43        + TCollection_AsciiString (Standard_Atomic_Increment (&THE_LIGHT_COUNTER));
44 }
45
46 // =======================================================================
47 // function : Graphic3d_CLight
48 // purpose  :
49 // =======================================================================
50 Graphic3d_CLight::Graphic3d_CLight (Graphic3d_TypeOfLightSource theType)
51 : myPosition   (0.0,  0.0,  0.0),
52   myColor      (1.0f, 1.0f, 1.0f, 1.0f),
53   myDirection  (0.0f, 0.0f, 0.0f, 0.0f),
54   myParams     (0.0f, 0.0f, 0.0f, 0.0f),
55   mySmoothness (0.0f),
56   myIntensity  (1.0f),
57   myType       (theType),
58   myRevision   (0),
59   myIsHeadlight(false),
60   myIsEnabled  (true),
61   myToCastShadows (false)
62 {
63   switch (theType)
64   {
65     case Graphic3d_TOLS_AMBIENT:
66     {
67       break;
68     }
69     case Graphic3d_TOLS_DIRECTIONAL:
70     {
71       mySmoothness = 0.2f;
72       myIntensity  = 20.0f;
73       break;
74     }
75     case Graphic3d_TOLS_POSITIONAL:
76     {
77       changeConstAttenuation()  = 1.0f;
78       changeLinearAttenuation() = 0.0f;
79       break;
80     }
81     case Graphic3d_TOLS_SPOT:
82     {
83       changeConstAttenuation()  = 1.0f;
84       changeLinearAttenuation() = 0.0f;
85       changeConcentration()     = 1.0f;
86       changeAngle()             = 0.523599f;
87       break;
88     }
89   }
90   makeId();
91 }
92
93 // =======================================================================
94 // function : SetColor
95 // purpose  :
96 // =======================================================================
97 void Graphic3d_CLight::SetColor (const Quantity_Color& theColor)
98 {
99   updateRevisionIf (myColor.GetRGB().IsDifferent (theColor));
100   myColor.SetRGB (theColor);
101 }
102
103 // =======================================================================
104 // function : SetEnabled
105 // purpose  :
106 // =======================================================================
107 void Graphic3d_CLight::SetEnabled (Standard_Boolean theIsOn)
108 {
109   updateRevisionIf (myIsEnabled != theIsOn);
110   myIsEnabled = theIsOn;
111 }
112
113 // =======================================================================
114 // function : SetCastShadows
115 // purpose  :
116 // =======================================================================
117 void Graphic3d_CLight::SetCastShadows (Standard_Boolean theToCast)
118 {
119   if (myType != Graphic3d_TOLS_DIRECTIONAL)
120   {
121     throw Standard_NotImplemented ("Graphic3d_CLight::SetCastShadows() is not implemented for this light type");
122   }
123   updateRevisionIf (myToCastShadows != theToCast);
124   myToCastShadows = theToCast;
125 }
126
127 // =======================================================================
128 // function : SetHeadlight
129 // purpose  :
130 // =======================================================================
131 void Graphic3d_CLight::SetHeadlight (Standard_Boolean theValue)
132 {
133   if (myType == Graphic3d_TOLS_AMBIENT)
134   {
135     throw Standard_ProgramError ("Graphic3d_CLight::SetHeadlight() is not applicable to ambient light");
136   }
137   updateRevisionIf (myIsHeadlight != theValue);
138   myIsHeadlight = theValue;
139 }
140
141 // =======================================================================
142 // function : SetDirection
143 // purpose  :
144 // =======================================================================
145 void Graphic3d_CLight::SetDirection (const gp_Dir& theDir)
146 {
147   Standard_ProgramError_Raise_if (myType != Graphic3d_TOLS_SPOT
148                                && myType != Graphic3d_TOLS_DIRECTIONAL,
149                                   "Graphic3d_CLight::SetDirection(), incorrect light type");
150   updateRevisionIf (Abs (myDirection.x() - static_cast<Standard_ShortReal> (theDir.X())) > ShortRealEpsilon()
151                  || Abs (myDirection.y() - static_cast<Standard_ShortReal> (theDir.Y())) > ShortRealEpsilon()
152                  || Abs (myDirection.z() - static_cast<Standard_ShortReal> (theDir.Z())) > ShortRealEpsilon());
153
154   myDirection.x() = static_cast<Standard_ShortReal> (theDir.X());
155   myDirection.y() = static_cast<Standard_ShortReal> (theDir.Y());
156   myDirection.z() = static_cast<Standard_ShortReal> (theDir.Z());
157 }
158
159 // =======================================================================
160 // function : SetPosition
161 // purpose  :
162 // =======================================================================
163 void Graphic3d_CLight::SetPosition (const gp_Pnt& thePosition)
164 {
165   Standard_ProgramError_Raise_if (myType != Graphic3d_TOLS_SPOT
166                                && myType != Graphic3d_TOLS_POSITIONAL,
167                                   "Graphic3d_CLight::SetPosition(), incorrect light type");
168   updateRevisionIf (!myPosition.IsEqual (thePosition, gp::Resolution()));
169   myPosition = thePosition;
170 }
171
172 // =======================================================================
173 // function : SetDisplayPosition
174 // purpose  :
175 // =======================================================================
176 void Graphic3d_CLight::SetDisplayPosition (const gp_Pnt& thePosition)
177 {
178   Standard_ProgramError_Raise_if (myType == Graphic3d_TOLS_AMBIENT,
179                                   "Graphic3d_CLight::SetDisplayPosition(), incorrect light type");
180   updateRevisionIf (!myPosition.IsEqual (thePosition, gp::Resolution()));
181   myPosition = thePosition;
182 }
183
184 // =======================================================================
185 // function : SetIntensity
186 // purpose  :
187 // =======================================================================
188 void Graphic3d_CLight::SetIntensity (Standard_ShortReal theValue)
189 {
190   Standard_OutOfRange_Raise_if (theValue <= 0.0f, "Graphic3d_CLight::SetIntensity(), Negative value for intensity");
191   updateRevisionIf (Abs (myIntensity - theValue) > ShortRealEpsilon());
192   myIntensity = theValue;
193 }
194
195 // =======================================================================
196 // function : SetAngle
197 // purpose  :
198 // =======================================================================
199 void Graphic3d_CLight::SetAngle (Standard_ShortReal theAngle)
200 {
201   Standard_ProgramError_Raise_if (myType != Graphic3d_TOLS_SPOT,
202                                   "Graphic3d_CLight::SetAngle(), incorrect light type");
203   Standard_OutOfRange_Raise_if (theAngle <= 0.0 || theAngle >= M_PI,
204                                 "Graphic3d_CLight::SetAngle(), bad angle");
205   updateRevisionIf (Abs (changeAngle() - theAngle) > ShortRealEpsilon());
206   changeAngle() = theAngle;
207 }
208
209 // =======================================================================
210 // function : SetAttenuation
211 // purpose  :
212 // =======================================================================
213 void Graphic3d_CLight::SetAttenuation (Standard_ShortReal theConstAttenuation,
214                                        Standard_ShortReal theLinearAttenuation)
215 {
216   Standard_ProgramError_Raise_if (myType != Graphic3d_TOLS_POSITIONAL
217                                && myType != Graphic3d_TOLS_SPOT,
218                                   "Graphic3d_CLight::SetAttenuation(), incorrect light type");
219   Standard_OutOfRange_Raise_if (theConstAttenuation  < 0.0f
220                              || theLinearAttenuation < 0.0f
221                              || theConstAttenuation + theLinearAttenuation == 0.0f, "Graphic3d_CLight::SetAttenuation(), bad coefficient");
222   updateRevisionIf (Abs (changeConstAttenuation()  - theConstAttenuation)  > ShortRealEpsilon()
223                  || Abs (changeLinearAttenuation() - theLinearAttenuation) > ShortRealEpsilon());
224   changeConstAttenuation()  = theConstAttenuation;
225   changeLinearAttenuation() = theLinearAttenuation;
226 }
227
228 // =======================================================================
229 // function : SetConcentration
230 // purpose  :
231 // =======================================================================
232 void Graphic3d_CLight::SetConcentration (Standard_ShortReal theConcentration)
233 {
234   Standard_ProgramError_Raise_if (myType != Graphic3d_TOLS_SPOT, "Graphic3d_CLight::SetConcentration(), incorrect light type");
235   Standard_OutOfRange_Raise_if (theConcentration < 0.0f || theConcentration > 1.0f,
236                                 "Graphic3d_CLight::SetConcentration(), bad coefficient");
237   updateRevisionIf (Abs (changeConcentration() - theConcentration) > ShortRealEpsilon());
238   changeConcentration() = theConcentration;
239 }
240
241 // =======================================================================
242 // function : SetSmoothRadius
243 // purpose  :
244 // =======================================================================
245 void Graphic3d_CLight::SetSmoothRadius (Standard_ShortReal theValue)
246 {
247   Standard_ProgramError_Raise_if (myType != Graphic3d_TOLS_POSITIONAL
248                                && myType != Graphic3d_TOLS_SPOT,
249                                   "Graphic3d_CLight::SetSmoothRadius(), incorrect light type");
250   Standard_OutOfRange_Raise_if (theValue < 0.0f, "Graphic3d_CLight::SetSmoothRadius(), Bad value for smoothing radius");
251   updateRevisionIf (Abs (mySmoothness - theValue) > ShortRealEpsilon());
252   mySmoothness = theValue;
253 }
254
255 // =======================================================================
256 // function : SetSmoothAngle
257 // purpose  :
258 // =======================================================================
259 void Graphic3d_CLight::SetSmoothAngle (Standard_ShortReal theValue)
260 {
261   Standard_ProgramError_Raise_if (myType != Graphic3d_TOLS_DIRECTIONAL,
262                                   "Graphic3d_CLight::SetSmoothAngle(), incorrect light type");
263   Standard_OutOfRange_Raise_if (theValue < 0.0f || theValue > Standard_ShortReal(M_PI / 2.0),
264                                 "Graphic3d_CLight::SetSmoothAngle(), Bad value for smoothing angle");
265   updateRevisionIf (Abs (mySmoothness - theValue) > ShortRealEpsilon());
266   mySmoothness = theValue;
267 }
268
269 // =======================================================================
270 // function : SetRange
271 // purpose  :
272 // =======================================================================
273 void Graphic3d_CLight::SetRange (Standard_ShortReal theValue)
274 {
275   Standard_ProgramError_Raise_if (myType != Graphic3d_TOLS_POSITIONAL && myType != Graphic3d_TOLS_SPOT,
276                                   "Graphic3d_CLight::SetRange(), incorrect light type");
277   Standard_OutOfRange_Raise_if (theValue < 0.0, "Graphic3d_CLight::SetRange(), Bad value for falloff range");
278   updateRevisionIf (Abs (Range() - theValue) > ShortRealEpsilon());
279   myDirection.w() = theValue;
280 };
281
282 //=======================================================================
283 //function : DumpJson
284 //purpose  : 
285 //=======================================================================
286 void Graphic3d_CLight::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const
287 {
288   OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
289   OCCT_DUMP_FIELD_VALUE_POINTER (theOStream, this)
290   
291   OCCT_DUMP_FIELD_VALUE_STRING (theOStream, myId)
292   OCCT_DUMP_FIELD_VALUE_STRING (theOStream, myName)
293   
294   if (myType == Graphic3d_TOLS_SPOT || myType == Graphic3d_TOLS_POSITIONAL)
295   {
296     OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myPosition)
297   }
298   OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myColor)
299   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIntensity)
300
301   if (myType == Graphic3d_TOLS_SPOT || myType == Graphic3d_TOLS_DIRECTIONAL)
302   {
303     gp_Dir aDirection = Direction();
304     OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &aDirection)
305   }
306   if (myType == Graphic3d_TOLS_POSITIONAL || myType == Graphic3d_TOLS_SPOT)
307   {
308     OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, ConstAttenuation())
309     OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, LinearAttenuation())
310   }
311   if (myType == Graphic3d_TOLS_SPOT)
312   {
313     OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, Angle())
314     OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, Concentration())
315   }
316   if (myType == Graphic3d_TOLS_POSITIONAL || myType == Graphic3d_TOLS_SPOT)
317   {
318     OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, Range())
319   }
320
321   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, mySmoothness)
322   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myType)
323   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myRevision)
324   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsHeadlight)
325   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsEnabled)
326 }