0032121: Draw Harness, ViewerTest - implement -reset option for vlight command
[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_TypeOfLightSource_Ambient:     aTypeSuffix = "amb"; break;
37     case Graphic3d_TypeOfLightSource_Directional: aTypeSuffix = "dir"; break;
38     case Graphic3d_TypeOfLightSource_Positional:  aTypeSuffix = "pos"; break;
39     case Graphic3d_TypeOfLightSource_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_TypeOfLightSource_Ambient:
66     {
67       break;
68     }
69     case Graphic3d_TypeOfLightSource_Directional:
70     {
71       mySmoothness = 0.2f;
72       myIntensity  = 20.0f;
73       break;
74     }
75     case Graphic3d_TypeOfLightSource_Positional:
76     {
77       changeConstAttenuation()  = 1.0f;
78       changeLinearAttenuation() = 0.0f;
79       break;
80     }
81     case Graphic3d_TypeOfLightSource_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 : CopyFrom
95 // purpose  :
96 // =======================================================================
97 void Graphic3d_CLight::CopyFrom (const Handle(Graphic3d_CLight)& theLight)
98 {
99   myName      = theLight->myName;
100   myIsEnabled = theLight->myIsEnabled;
101   myIntensity = theLight->myIntensity;
102   myColor     = theLight->myColor;
103   if (myType != Graphic3d_TypeOfLightSource_Ambient)
104   {
105     myPosition    = theLight->myPosition;
106     myIsHeadlight = theLight->myIsHeadlight;
107   }
108   if ((myType == Graphic3d_TypeOfLightSource_Spot
109     || myType == Graphic3d_TypeOfLightSource_Directional)
110    && (theLight->myType == Graphic3d_TypeOfLightSource_Spot
111     || theLight->myType == Graphic3d_TypeOfLightSource_Directional))
112   {
113     myDirection = theLight->myDirection;
114   }
115   if (myType == Graphic3d_TypeOfLightSource_Directional)
116   {
117     myToCastShadows = theLight->myToCastShadows;
118   }
119   if (myType == theLight->myType)
120   {
121     myParams     = theLight->myParams;
122     mySmoothness = theLight->mySmoothness;
123   }
124 }
125
126 // =======================================================================
127 // function : SetColor
128 // purpose  :
129 // =======================================================================
130 void Graphic3d_CLight::SetColor (const Quantity_Color& theColor)
131 {
132   updateRevisionIf (myColor.GetRGB().IsDifferent (theColor));
133   myColor.SetRGB (theColor);
134 }
135
136 // =======================================================================
137 // function : SetEnabled
138 // purpose  :
139 // =======================================================================
140 void Graphic3d_CLight::SetEnabled (Standard_Boolean theIsOn)
141 {
142   updateRevisionIf (myIsEnabled != theIsOn);
143   myIsEnabled = theIsOn;
144 }
145
146 // =======================================================================
147 // function : SetCastShadows
148 // purpose  :
149 // =======================================================================
150 void Graphic3d_CLight::SetCastShadows (Standard_Boolean theToCast)
151 {
152   if (myType != Graphic3d_TypeOfLightSource_Directional)
153   {
154     throw Standard_NotImplemented ("Graphic3d_CLight::SetCastShadows() is not implemented for this light type");
155   }
156   updateRevisionIf (myToCastShadows != theToCast);
157   myToCastShadows = theToCast;
158 }
159
160 // =======================================================================
161 // function : SetHeadlight
162 // purpose  :
163 // =======================================================================
164 void Graphic3d_CLight::SetHeadlight (Standard_Boolean theValue)
165 {
166   if (myType == Graphic3d_TypeOfLightSource_Ambient)
167   {
168     throw Standard_ProgramError ("Graphic3d_CLight::SetHeadlight() is not applicable to ambient light");
169   }
170   updateRevisionIf (myIsHeadlight != theValue);
171   myIsHeadlight = theValue;
172 }
173
174 // =======================================================================
175 // function : SetDirection
176 // purpose  :
177 // =======================================================================
178 void Graphic3d_CLight::SetDirection (const gp_Dir& theDir)
179 {
180   Standard_ProgramError_Raise_if (myType != Graphic3d_TypeOfLightSource_Spot
181                                && myType != Graphic3d_TypeOfLightSource_Directional,
182                                   "Graphic3d_CLight::SetDirection(), incorrect light type");
183   updateRevisionIf (Abs (myDirection.x() - static_cast<Standard_ShortReal> (theDir.X())) > ShortRealEpsilon()
184                  || Abs (myDirection.y() - static_cast<Standard_ShortReal> (theDir.Y())) > ShortRealEpsilon()
185                  || Abs (myDirection.z() - static_cast<Standard_ShortReal> (theDir.Z())) > ShortRealEpsilon());
186
187   myDirection.x() = static_cast<Standard_ShortReal> (theDir.X());
188   myDirection.y() = static_cast<Standard_ShortReal> (theDir.Y());
189   myDirection.z() = static_cast<Standard_ShortReal> (theDir.Z());
190 }
191
192 // =======================================================================
193 // function : SetPosition
194 // purpose  :
195 // =======================================================================
196 void Graphic3d_CLight::SetPosition (const gp_Pnt& thePosition)
197 {
198   Standard_ProgramError_Raise_if (myType != Graphic3d_TypeOfLightSource_Spot
199                                && myType != Graphic3d_TypeOfLightSource_Positional,
200                                   "Graphic3d_CLight::SetPosition(), incorrect light type");
201   updateRevisionIf (!myPosition.IsEqual (thePosition, gp::Resolution()));
202   myPosition = thePosition;
203 }
204
205 // =======================================================================
206 // function : SetDisplayPosition
207 // purpose  :
208 // =======================================================================
209 void Graphic3d_CLight::SetDisplayPosition (const gp_Pnt& thePosition)
210 {
211   Standard_ProgramError_Raise_if (myType == Graphic3d_TypeOfLightSource_Ambient,
212                                   "Graphic3d_CLight::SetDisplayPosition(), incorrect light type");
213   updateRevisionIf (!myPosition.IsEqual (thePosition, gp::Resolution()));
214   myPosition = thePosition;
215 }
216
217 // =======================================================================
218 // function : SetIntensity
219 // purpose  :
220 // =======================================================================
221 void Graphic3d_CLight::SetIntensity (Standard_ShortReal theValue)
222 {
223   Standard_OutOfRange_Raise_if (theValue <= 0.0f, "Graphic3d_CLight::SetIntensity(), Negative value for intensity");
224   updateRevisionIf (Abs (myIntensity - theValue) > ShortRealEpsilon());
225   myIntensity = theValue;
226 }
227
228 // =======================================================================
229 // function : SetAngle
230 // purpose  :
231 // =======================================================================
232 void Graphic3d_CLight::SetAngle (Standard_ShortReal theAngle)
233 {
234   Standard_ProgramError_Raise_if (myType != Graphic3d_TypeOfLightSource_Spot,
235                                   "Graphic3d_CLight::SetAngle(), incorrect light type");
236   Standard_OutOfRange_Raise_if (theAngle <= 0.0 || theAngle >= M_PI,
237                                 "Graphic3d_CLight::SetAngle(), bad angle");
238   updateRevisionIf (Abs (changeAngle() - theAngle) > ShortRealEpsilon());
239   changeAngle() = theAngle;
240 }
241
242 // =======================================================================
243 // function : SetAttenuation
244 // purpose  :
245 // =======================================================================
246 void Graphic3d_CLight::SetAttenuation (Standard_ShortReal theConstAttenuation,
247                                        Standard_ShortReal theLinearAttenuation)
248 {
249   Standard_ProgramError_Raise_if (myType != Graphic3d_TypeOfLightSource_Positional
250                                && myType != Graphic3d_TypeOfLightSource_Spot,
251                                   "Graphic3d_CLight::SetAttenuation(), incorrect light type");
252   Standard_OutOfRange_Raise_if (theConstAttenuation  < 0.0f
253                              || theLinearAttenuation < 0.0f
254                              || theConstAttenuation + theLinearAttenuation == 0.0f, "Graphic3d_CLight::SetAttenuation(), bad coefficient");
255   updateRevisionIf (Abs (changeConstAttenuation()  - theConstAttenuation)  > ShortRealEpsilon()
256                  || Abs (changeLinearAttenuation() - theLinearAttenuation) > ShortRealEpsilon());
257   changeConstAttenuation()  = theConstAttenuation;
258   changeLinearAttenuation() = theLinearAttenuation;
259 }
260
261 // =======================================================================
262 // function : SetConcentration
263 // purpose  :
264 // =======================================================================
265 void Graphic3d_CLight::SetConcentration (Standard_ShortReal theConcentration)
266 {
267   Standard_ProgramError_Raise_if (myType != Graphic3d_TypeOfLightSource_Spot, "Graphic3d_CLight::SetConcentration(), incorrect light type");
268   Standard_OutOfRange_Raise_if (theConcentration < 0.0f || theConcentration > 1.0f,
269                                 "Graphic3d_CLight::SetConcentration(), bad coefficient");
270   updateRevisionIf (Abs (changeConcentration() - theConcentration) > ShortRealEpsilon());
271   changeConcentration() = theConcentration;
272 }
273
274 // =======================================================================
275 // function : SetSmoothRadius
276 // purpose  :
277 // =======================================================================
278 void Graphic3d_CLight::SetSmoothRadius (Standard_ShortReal theValue)
279 {
280   Standard_ProgramError_Raise_if (myType != Graphic3d_TypeOfLightSource_Positional
281                                && myType != Graphic3d_TypeOfLightSource_Spot,
282                                   "Graphic3d_CLight::SetSmoothRadius(), incorrect light type");
283   Standard_OutOfRange_Raise_if (theValue < 0.0f, "Graphic3d_CLight::SetSmoothRadius(), Bad value for smoothing radius");
284   updateRevisionIf (Abs (mySmoothness - theValue) > ShortRealEpsilon());
285   mySmoothness = theValue;
286 }
287
288 // =======================================================================
289 // function : SetSmoothAngle
290 // purpose  :
291 // =======================================================================
292 void Graphic3d_CLight::SetSmoothAngle (Standard_ShortReal theValue)
293 {
294   Standard_ProgramError_Raise_if (myType != Graphic3d_TypeOfLightSource_Directional,
295                                   "Graphic3d_CLight::SetSmoothAngle(), incorrect light type");
296   Standard_OutOfRange_Raise_if (theValue < 0.0f || theValue > Standard_ShortReal(M_PI / 2.0),
297                                 "Graphic3d_CLight::SetSmoothAngle(), Bad value for smoothing angle");
298   updateRevisionIf (Abs (mySmoothness - theValue) > ShortRealEpsilon());
299   mySmoothness = theValue;
300 }
301
302 // =======================================================================
303 // function : SetRange
304 // purpose  :
305 // =======================================================================
306 void Graphic3d_CLight::SetRange (Standard_ShortReal theValue)
307 {
308   Standard_ProgramError_Raise_if (myType != Graphic3d_TypeOfLightSource_Positional
309                                && myType != Graphic3d_TypeOfLightSource_Spot,
310                                   "Graphic3d_CLight::SetRange(), incorrect light type");
311   Standard_OutOfRange_Raise_if (theValue < 0.0, "Graphic3d_CLight::SetRange(), Bad value for falloff range");
312   updateRevisionIf (Abs (Range() - theValue) > ShortRealEpsilon());
313   myDirection.w() = theValue;
314 };
315
316 //=======================================================================
317 //function : DumpJson
318 //purpose  : 
319 //=======================================================================
320 void Graphic3d_CLight::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const
321 {
322   OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
323   OCCT_DUMP_FIELD_VALUE_POINTER (theOStream, this)
324   
325   OCCT_DUMP_FIELD_VALUE_STRING (theOStream, myId)
326   OCCT_DUMP_FIELD_VALUE_STRING (theOStream, myName)
327   
328   if (myType == Graphic3d_TypeOfLightSource_Spot || myType == Graphic3d_TypeOfLightSource_Positional)
329   {
330     OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myPosition)
331   }
332   OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myColor)
333   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIntensity)
334
335   if (myType == Graphic3d_TypeOfLightSource_Spot || myType == Graphic3d_TypeOfLightSource_Directional)
336   {
337     gp_Dir aDirection = Direction();
338     OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &aDirection)
339   }
340   if (myType == Graphic3d_TypeOfLightSource_Positional || myType == Graphic3d_TypeOfLightSource_Spot)
341   {
342     OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, ConstAttenuation())
343     OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, LinearAttenuation())
344   }
345   if (myType == Graphic3d_TypeOfLightSource_Spot)
346   {
347     OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, Angle())
348     OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, Concentration())
349   }
350   if (myType == Graphic3d_TypeOfLightSource_Positional || myType == Graphic3d_TypeOfLightSource_Spot)
351   {
352     OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, Range())
353   }
354
355   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, mySmoothness)
356   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myType)
357   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myRevision)
358   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsHeadlight)
359   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsEnabled)
360 }