c2f4b0470e5743943641507ed717f48c3938ea59
[occt.git] / src / Visual3d / Visual3d_Light.cxx
1 // Copyright (c) 1995-1999 Matra Datavision
2 // Copyright (c) 1999-2012 OPEN CASCADE SAS
3 //
4 // The content of this file is subject to the Open CASCADE Technology Public
5 // License Version 6.5 (the "License"). You may not use the content of this file
6 // except in compliance with the License. Please obtain a copy of the License
7 // at http://www.opencascade.org and read it completely before using this file.
8 //
9 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
10 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
11 //
12 // The Original Code and all software distributed under the License is
13 // distributed on an "AS IS" basis, without warranty of any kind, and the
14 // Initial Developer hereby disclaims all such warranties, including without
15 // limitation, any warranties of merchantability, fitness for a particular
16 // purpose or non-infringement. Please see the License for the specific terms
17 // and conditions governing the rights and limitations under the License.
18
19 /***********************************************************************
20
21      FUNCTION :
22      ----------
23         File Visual3d_Light :
24
25         Declaration of variables specific to light sources
26
27      NOTES:
28      ----------
29
30         A light source is defined by :
31         - type
32         - color
33         - reduction factors  ( for positional and spot only )
34         - its angle ( for spot only )
35         - its concentration ( for spot only )
36         - its direction ( directional and spot only )
37         - its position ( positional and spot only )
38
39         It is active in a view, in the associated context.
40
41      ATTENTION:
42      ----------
43
44         - AngleCone is given in radian [Pex] while OpenGl works in 
45         degreees. The limits for Pex are [0,PI] while for OpenGl this is [0,90].
46         - Two reduction factors are used with Pex while OpenGl uses three.
47         - The ereduction factors have range [0.0,1.0] for Pex and 
48         for OpenGl the range is [0.0,n] 
49         - The concentration varies from [0.,1.0] for Pex to [0,128] for OpenGl. 
50
51 ************************************************************************/
52
53 /*----------------------------------------------------------------------*/
54 /*
55  * Includes
56  */ 
57
58 #include <Visual3d_Light.ixx>
59
60 #include <Graphic3d_GraphicDriver.hxx>
61
62 /*----------------------------------------------------------------------*/
63
64 Visual3d_Light::Visual3d_Light ():
65 MyType (Visual3d_TOLS_AMBIENT) {
66
67         MyCLight.WsId           = -1;
68         MyCLight.ViewId         = 0; /* not used */
69         MyCLight.LightType      = int (MyType);
70         MyCLight.Headlight      = 0;
71
72 Quantity_Color White (Quantity_NOC_WHITE);
73
74         MyCLight.Color.r        = float (White.Red ());
75         MyCLight.Color.g        = float (White.Green ());
76         MyCLight.Color.b        = float (White.Blue ());
77
78         MyCLight.LightId        =
79                 Graphic3d_GraphicDriver::Light (MyCLight, Standard_False);
80
81 }
82
83 /*----------------------------------------------------------------------*/
84
85 Visual3d_Light::Visual3d_Light (const Quantity_Color& Color):
86 MyType (Visual3d_TOLS_AMBIENT) {
87
88         MyCLight.WsId           = -1;
89         MyCLight.ViewId         = 0; /* not used */
90         MyCLight.LightType      = int (MyType);
91         MyCLight.Headlight      = 0;
92
93         MyCLight.Color.r        = float (Color.Red ());
94         MyCLight.Color.g        = float (Color.Green ());
95         MyCLight.Color.b        = float (Color.Blue ());
96
97         MyCLight.LightId        =
98                 Graphic3d_GraphicDriver::Light (MyCLight, Standard_False);
99
100 }
101
102 /*----------------------------------------------------------------------*/
103
104 Visual3d_Light::Visual3d_Light(const Quantity_Color& Color,const Graphic3d_Vector& Direction,const Standard_Boolean Headlight): MyType (Visual3d_TOLS_DIRECTIONAL) {
105
106         if (Direction.LengthZero ())
107                 Visual3d_LightDefinitionError::Raise
108                         ("Bad value for LightDirection");
109
110         MyCLight.WsId           = -1;
111         MyCLight.ViewId         = 0; /* not used */
112         MyCLight.LightType      = int (MyType);
113         MyCLight.Headlight      = Headlight? 1:0;
114
115 Standard_Real Norme, X, Y, Z;
116
117         Color.Values (X, Y, Z, Quantity_TOC_RGB);
118         MyCLight.Color.r        = float (X);
119         MyCLight.Color.g        = float (Y);
120         MyCLight.Color.b        = float (Z);
121
122         Direction.Coord (X, Y, Z);
123         Norme   = Sqrt (X*X+Y*Y+Z*Z);
124         // Direction.LengthZero () == Standard_False
125         MyCLight.Direction.x    = float (X/Norme);
126         MyCLight.Direction.y    = float (Y/Norme);
127         MyCLight.Direction.z    = float (Z/Norme);
128
129         MyCLight.LightId        =
130                 Graphic3d_GraphicDriver::Light (MyCLight, Standard_False);
131
132 }
133
134 /*----------------------------------------------------------------------*/
135
136 Visual3d_Light::Visual3d_Light (const Quantity_Color& Color, const Graphic3d_Vertex& Position, const Standard_Real Fact1, const Standard_Real Fact2):
137 MyType (Visual3d_TOLS_POSITIONAL) {
138
139         if ( (Fact1 == 0.0) && (Fact2 == 0.0) )
140                 Visual3d_LightDefinitionError::Raise
141                         ("Bad value for LightAttenuation");
142
143         if ( (Fact1 < 0.0) && (Fact1 > 1.0) )
144                 Visual3d_LightDefinitionError::Raise
145                         ("Bad value for LightAttenuation");
146
147         if ( (Fact2 < 0.0) && (Fact2 > 1.0) )
148                 Visual3d_LightDefinitionError::Raise
149                         ("Bad value for LightAttenuation");
150
151         MyCLight.WsId           = -1;
152         MyCLight.ViewId         = 0; /* not used */
153         MyCLight.LightType      = int (MyType);
154         MyCLight.Headlight      = 0;
155
156         MyCLight.Color.r        = float (Color.Red ());
157         MyCLight.Color.g        = float (Color.Green ());
158         MyCLight.Color.b        = float (Color.Blue ());
159
160         MyCLight.Position.x     = float (Position.X ());
161         MyCLight.Position.y     = float (Position.Y ());
162         MyCLight.Position.z     = float (Position.Z ());
163
164         MyCLight.Attenuation[0] = float (Fact1);
165         MyCLight.Attenuation[1] = float (Fact2);
166
167         MyCLight.LightId        =
168                 Graphic3d_GraphicDriver::Light (MyCLight, Standard_False);
169
170 }
171
172 /*----------------------------------------------------------------------*/
173
174 Visual3d_Light::Visual3d_Light (const Quantity_Color& Color, const Graphic3d_Vertex& Position, const Graphic3d_Vector& Direction, const Standard_Real Concentration, const Standard_Real Fact1, const Standard_Real Fact2, const Standard_Real AngleCone):
175 MyType (Visual3d_TOLS_SPOT) {
176
177         if (Direction.LengthZero ())
178                 Visual3d_LightDefinitionError::Raise
179                         ("Bad value for LightDirection");
180
181         if ( (Concentration < 0.0) || (Concentration > 1.0) )
182                 Visual3d_LightDefinitionError::Raise
183                         ("Bad value for LightConcentration");
184
185         if ( (Fact1 == 0.0) && (Fact2 == 0.0) )
186                 Visual3d_LightDefinitionError::Raise
187                         ("Bad value for LightAttenuation");
188
189         if ( (Fact1 < 0.0) && (Fact1 > 1.0) )
190                 Visual3d_LightDefinitionError::Raise
191                         ("Bad value for LightAttenuation");
192
193         if ( (Fact2 < 0.0) && (Fact2 > 1.0) )
194                 Visual3d_LightDefinitionError::Raise
195                         ("Bad value for LightAttenuation");
196
197         if (Visual3d_Light::IsValid (AngleCone)) {
198
199                 MyCLight.WsId           = -1;
200                 MyCLight.ViewId         = 0; /* not used */
201                 MyCLight.LightType      = int (MyType);
202                 MyCLight.Headlight      = 0;
203
204 Standard_Real X, Y, Z;
205
206                 Color.Values (X, Y, Z, Quantity_TOC_RGB);
207                 MyCLight.Color.r        = float (X);
208                 MyCLight.Color.g        = float (Y);
209                 MyCLight.Color.b        = float (Z);
210
211                 Position.Coord (X, Y, Z);
212                 MyCLight.Position.x     = float (X);
213                 MyCLight.Position.y     = float (Y);
214                 MyCLight.Position.z     = float (Z);
215
216                 Direction.Coord (X, Y, Z);
217                 MyCLight.Direction.x    = float (X);
218                 MyCLight.Direction.y    = float (Y);
219                 MyCLight.Direction.z    = float (Z);
220
221                 MyCLight.Concentration  = float (Concentration);
222
223                 MyCLight.Attenuation[0] = float (Fact1);
224                 MyCLight.Attenuation[1] = float (Fact2);
225
226                 MyCLight.Angle          = float (AngleCone);
227
228                 MyCLight.LightId        =
229                   Graphic3d_GraphicDriver::Light (MyCLight, Standard_False);
230
231         }
232         else
233                 Visual3d_LightDefinitionError::Raise
234                         ("Bad value for LightAngle");
235
236 }
237
238 /*----------------------------------------------------------------------*/
239
240 Quantity_Color Visual3d_Light::Color () const {
241
242 Quantity_Color AColor  (Standard_Real (MyCLight.Color.r),
243                         Standard_Real (MyCLight.Color.g),
244                         Standard_Real (MyCLight.Color.b),
245                         Quantity_TOC_RGB);
246
247         return (AColor);
248
249 }
250
251 /*----------------------------------------------------------------------*/
252
253 Visual3d_TypeOfLightSource Visual3d_Light::LightType () const {
254
255         return (MyType);
256
257 }
258
259 /*----------------------------------------------------------------------*/
260 Standard_Boolean Visual3d_Light::Headlight () const {
261   return MyCLight.Headlight==0? Standard_False:Standard_True;
262 }
263
264 /*----------------------------------------------------------------------*/
265
266 void Visual3d_Light::Values (Quantity_Color& Color) const {
267
268 Quantity_Color AColor  (Standard_Real (MyCLight.Color.r),
269                         Standard_Real (MyCLight.Color.g),
270                         Standard_Real (MyCLight.Color.b),
271                         Quantity_TOC_RGB);
272
273         if (MyType == Visual3d_TOLS_AMBIENT)
274                 Color           = AColor;
275         else Visual3d_LightDefinitionError::Raise
276                 ("Light Type != Visual3d_TOLS_AMBIENT");
277
278 }
279
280 /*----------------------------------------------------------------------*/
281
282 void Visual3d_Light::Values (Quantity_Color& Color, Graphic3d_Vector& Direction) const {
283
284 Quantity_Color AColor  (Standard_Real (MyCLight.Color.r),
285                         Standard_Real (MyCLight.Color.g),
286                         Standard_Real (MyCLight.Color.b),
287                         Quantity_TOC_RGB);
288
289 Graphic3d_Vector ADirection    (Standard_Real (MyCLight.Direction.x),
290                                 Standard_Real (MyCLight.Direction.y),
291                                 Standard_Real (MyCLight.Direction.z));
292
293         if (MyType == Visual3d_TOLS_DIRECTIONAL) {
294                 Color           = AColor;
295                 Direction       = ADirection;
296         }
297         else Visual3d_LightDefinitionError::Raise
298                 ("Light Type != Visual3d_TOLS_DIRECTIONAL");
299
300 }
301
302 /*----------------------------------------------------------------------*/
303
304 void Visual3d_Light::Values (Quantity_Color& Color, Graphic3d_Vertex& Position, Standard_Real& Fact1, Standard_Real& Fact2) const {
305
306 Quantity_Color AColor  (Standard_Real (MyCLight.Color.r),
307                         Standard_Real (MyCLight.Color.g),
308                         Standard_Real (MyCLight.Color.b),
309                         Quantity_TOC_RGB);
310
311 Graphic3d_Vertex APosition     (Standard_Real (MyCLight.Position.x),
312                                 Standard_Real (MyCLight.Position.y),
313                                 Standard_Real (MyCLight.Position.z));
314
315         if (MyType == Visual3d_TOLS_POSITIONAL) {
316                 Color           = AColor;
317                 Position        = APosition;
318                 Fact1           = Standard_Real (MyCLight.Attenuation[0]);
319                 Fact2           = Standard_Real (MyCLight.Attenuation[1]);
320         }
321         else Visual3d_LightDefinitionError::Raise
322                 ("Light Type != Visual3d_TOLS_POSITIONAL");
323
324 }
325
326 /*----------------------------------------------------------------------*/
327
328 void Visual3d_Light::Values (Quantity_Color& Color, Graphic3d_Vertex& Position, Graphic3d_Vector& Direction, Standard_Real& Concentration, Standard_Real& Fact1, Standard_Real& Fact2, Standard_Real& AngleCone) const {
329
330 Quantity_Color AColor  (Standard_Real (MyCLight.Color.r),
331                         Standard_Real (MyCLight.Color.g),
332                         Standard_Real (MyCLight.Color.b),
333                         Quantity_TOC_RGB);
334
335 Graphic3d_Vertex APosition     (Standard_Real (MyCLight.Position.x),
336                                 Standard_Real (MyCLight.Position.y),
337                                 Standard_Real (MyCLight.Position.z));
338
339 Graphic3d_Vector ADirection    (Standard_Real (MyCLight.Direction.x),
340                                 Standard_Real (MyCLight.Direction.y),
341                                 Standard_Real (MyCLight.Direction.z));
342
343         if (MyType == Visual3d_TOLS_SPOT) {
344                 Color           = AColor;
345                 Position        = APosition;
346                 Direction       = ADirection;
347                 Concentration   = Standard_Real (MyCLight.Concentration);
348                 Fact1           = Standard_Real (MyCLight.Attenuation[0]);
349                 Fact2           = Standard_Real (MyCLight.Attenuation[1]);
350                 AngleCone       = Standard_Real (MyCLight.Angle);
351         }
352         else Visual3d_LightDefinitionError::Raise
353                 ("Light Type != Visual3d_TOLS_SPOT");
354
355 }
356
357 /*----------------------------------------------------------------------*/
358
359 void Visual3d_Light::SetAngle (const Standard_Real AngleCone) {
360
361         if (! Visual3d_Light::IsValid (AngleCone))
362                 Visual3d_LightDefinitionError::Raise
363                         ("Bad value for LightAngle");
364
365         if (MyType == Visual3d_TOLS_SPOT) {
366                 MyCLight.Angle  = float (AngleCone);
367
368                 MyCLight.LightId        =
369                   Graphic3d_GraphicDriver::Light (MyCLight, Standard_True);
370
371         }
372         else Visual3d_LightDefinitionError::Raise
373                 ("Light Type != Visual3d_TOLS_SPOT");
374
375 }
376
377 /*----------------------------------------------------------------------*/
378
379 void Visual3d_Light::SetAttenuation1 (const Standard_Real Fact1) {
380
381         if ( (Fact1 < 0.0) && (Fact1 > 1.0) )
382                 Visual3d_LightDefinitionError::Raise
383                         ("Bad value for LightAttenuation");
384
385         if ( (MyType == Visual3d_TOLS_POSITIONAL) ||
386              (MyType == Visual3d_TOLS_SPOT) ) {
387                 MyCLight.Attenuation[0] = float (Fact1);
388
389                 MyCLight.LightId        =
390                   Graphic3d_GraphicDriver::Light (MyCLight, Standard_True);
391
392         }
393         else Visual3d_LightDefinitionError::Raise
394         ("Light Type != Visual3d_TOLS_POSITIONAL and != Visual3d_TOLS_SPOT");
395
396 }
397
398 /*----------------------------------------------------------------------*/
399
400 void Visual3d_Light::SetAttenuation2 (const Standard_Real Fact2) {
401
402         if ( (Fact2 < 0.0) && (Fact2 > 1.0) )
403                 Visual3d_LightDefinitionError::Raise
404                         ("Bad value for LightAttenuation");
405
406         if ( (MyType == Visual3d_TOLS_POSITIONAL) ||
407              (MyType == Visual3d_TOLS_SPOT) ) {
408                 MyCLight.Attenuation[1] = float (Fact2);
409
410                 MyCLight.LightId        =
411                   Graphic3d_GraphicDriver::Light (MyCLight, Standard_True);
412
413         }
414         else Visual3d_LightDefinitionError::Raise
415         ("Light Type != Visual3d_TOLS_POSITIONAL and != Visual3d_TOLS_SPOT");
416
417 }
418
419 /*----------------------------------------------------------------------*/
420
421 void Visual3d_Light::SetColor (const Quantity_Color& Color) {
422
423         MyCLight.Color.r        = float (Color.Red ());
424         MyCLight.Color.g        = float (Color.Green ());
425         MyCLight.Color.b        = float (Color.Blue ());
426
427         MyCLight.LightId        =
428                   Graphic3d_GraphicDriver::Light (MyCLight, Standard_True);
429
430 }
431
432 /*----------------------------------------------------------------------*/
433
434 void Visual3d_Light::SetConcentration (const Standard_Real Concentration) {
435
436         if ( (Concentration < 0.0) || (Concentration > 1.0) )
437                 Visual3d_LightDefinitionError::Raise
438                         ("Bad value for LightConcentration");
439
440         if (MyType == Visual3d_TOLS_SPOT) {
441                 MyCLight.Concentration  = float (Concentration);
442
443                 MyCLight.LightId        =
444                   Graphic3d_GraphicDriver::Light (MyCLight, Standard_True);
445         }
446         else Visual3d_LightDefinitionError::Raise
447                 ("Light Type != Visual3d_TOLS_SPOT");
448
449 }
450
451 /*----------------------------------------------------------------------*/
452
453 void Visual3d_Light::SetDirection (const Graphic3d_Vector& Direction) {
454
455         if (Direction.LengthZero ())
456                 Visual3d_LightDefinitionError::Raise
457                         ("Bad value for LightDirection");
458
459         if ( (MyType == Visual3d_TOLS_DIRECTIONAL) ||
460              (MyType == Visual3d_TOLS_SPOT) ) {
461
462 Standard_Real Norme, X, Y, Z;
463                 Direction.Coord (X, Y, Z);
464                 Norme   = Sqrt (X*X+Y*Y+Z*Z);
465                 // Direction.LengthZero () == Standard_False
466                 MyCLight.Direction.x    = float (X/Norme);
467                 MyCLight.Direction.y    = float (Y/Norme);
468                 MyCLight.Direction.z    = float (Z/Norme);
469
470                 MyCLight.LightId        =
471                   Graphic3d_GraphicDriver::Light (MyCLight, Standard_True);
472
473         }
474         else Visual3d_LightDefinitionError::Raise
475         ("Light Type != Visual3d_TOLS_DIRECTIONAL and != Visual3d_TOLS_SPOT");
476
477 }
478
479 /*----------------------------------------------------------------------*/
480
481 void Visual3d_Light::SetPosition (const Graphic3d_Vertex& Position) {
482
483         if ( (MyType == Visual3d_TOLS_POSITIONAL) ||
484              (MyType == Visual3d_TOLS_SPOT) ) {
485
486                 MyCLight.Position.x     = float (Position.X ());
487                 MyCLight.Position.y     = float (Position.Y ());
488                 MyCLight.Position.z     = float (Position.Z ());
489
490                 MyCLight.LightId        =
491                   Graphic3d_GraphicDriver::Light (MyCLight, Standard_True);
492
493         }
494         else Visual3d_LightDefinitionError::Raise
495         ("Light Type != Visual3d_TOLS_POSITIONAL and != Visual3d_TOLS_SPOT");
496
497 }
498
499 /*----------------------------------------------------------------------*/
500
501 Standard_Integer Visual3d_Light::Limit () {
502
503         // Old method, replaced by GraphicDriver::InquireLightLimit ()
504         return 0;
505
506 }
507
508 /*----------------------------------------------------------------------*/
509
510 Standard_Integer Visual3d_Light::Identification () const {
511
512         return (Standard_Integer (MyCLight.LightId));
513
514 }
515
516 /*----------------------------------------------------------------------*/
517
518 Standard_Boolean Visual3d_Light::IsValid (const Standard_Real AAngle) {
519
520         return ( (AAngle <  M_PI) && (AAngle >= 0.0) );
521
522 }
523
524 /*----------------------------------------------------------------------*/