1 /**************************************************************************\
2  * Copyright (c) Kongsberg Oil & Gas Technologies AS
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * Redistributions of source code must retain the above copyright notice,
10  * this list of conditions and the following disclaimer.
11  *
12  * Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in the
14  * documentation and/or other materials provided with the distribution.
15  *
16  * Neither the name of the copyright holder nor the names of its
17  * contributors may be used to endorse or promote products derived from
18  * this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 \**************************************************************************/
32 
33 /*!
34   \class SoDirectionalLight SoDirectionalLight.h Inventor/nodes/SoDirectionalLight.h
35   \brief The SoDirectionalLight class is a node type for specifying directional light sources.
36 
37   \ingroup nodes
38 
39   A directional light source provides a model of light sources which
40   are at infinite distance from the geometry it illuminates, thereby
41   having no set position and consisting of an infinite volume of
42   parallel rays.
43 
44   This is of course a simplified model of far-away light sources, as
45   "infinite distance" is impossible.
46 
47   The sun shining on objects on earth is a good example of something
48   which can be modeled rather well for the most common purposes with a
49   directional light source.
50 
51   See also documentation of parent class for important information
52   regarding light sources in general.
53 
54   <b>FILE FORMAT/DEFAULTS:</b>
55   \code
56     DirectionalLight {
57         on TRUE
58         intensity 1
59         color 1 1 1
60         direction 0 0 -1
61     }
62   \endcode
63 
64 
65   A common thing to do with an SoDirectionalLight is to connect it to
66   a camera, so it works in the style of a head light to that camera.
67   This can easily be accomplished by linking an SoRotation::rotation
68   field, influencing the light, to the SoCamera::orientation
69   field. Here is a complete example iv-file demonstrating the
70   technique:
71 
72   \verbatim
73   #Inventor V2.1 ascii
74 
75   DEF mycam PerspectiveCamera { }
76 
77   TransformSeparator {
78      SoRotation { rotation = USE mycam.orientation }
79      DirectionalLight { direction 0 0 -1 }
80   }
81 
82   Cube { }
83   \endverbatim
84 
85   (The SoTransformSeparator is included to keep the effect of the
86   SoRotation node within a scope where it will only influence the
87   light, and not the geometry following the light in the scene graph.)
88 */
89 
90 // *************************************************************************
91 
92 #include <Inventor/nodes/SoDirectionalLight.h>
93 
94 #ifdef HAVE_CONFIG_H
95 #include "config.h"
96 #endif // HAVE_CONFIG_H
97 
98 #include <Inventor/SbColor4f.h>
99 #include <Inventor/SbVec4f.h>
100 #include <Inventor/actions/SoGLRenderAction.h>
101 #include <Inventor/elements/SoEnvironmentElement.h>
102 #include <Inventor/elements/SoGLLightIdElement.h>
103 #include <Inventor/elements/SoLightElement.h>
104 #include <Inventor/elements/SoModelMatrixElement.h>
105 #include <Inventor/elements/SoViewingMatrixElement.h>
106 #include <Inventor/errors/SoDebugError.h>
107 #include <Inventor/system/gl.h>
108 
109 #include "nodes/SoSubNodeP.h"
110 
111 // *************************************************************************
112 
113 /*!
114   \var SoSFVec3f SoDirectionalLight::direction
115 
116   The direction of the light source. Defaults to pointing along the
117   negative z-axis.
118 */
119 
120 // *************************************************************************
121 
122 SO_NODE_SOURCE(SoDirectionalLight);
123 
124 // *************************************************************************
125 
126 /*!
127   Constructor.
128 */
SoDirectionalLight(void)129 SoDirectionalLight::SoDirectionalLight(void)
130 {
131   SO_NODE_INTERNAL_CONSTRUCTOR(SoDirectionalLight);
132 
133   SO_NODE_ADD_FIELD(direction, (0.0f, 0.0f, -1.0f));
134 }
135 
136 /*!
137   Destructor.
138 */
~SoDirectionalLight()139 SoDirectionalLight::~SoDirectionalLight()
140 {
141 }
142 
143 // Doc from superclass.
144 void
initClass(void)145 SoDirectionalLight::initClass(void)
146 {
147   SO_NODE_INTERNAL_INIT_CLASS(SoDirectionalLight, SO_FROM_INVENTOR_1|SoNode::VRML1);
148 }
149 
150 // *************************************************************************
151 
152 // Doc from superclass.
153 void
GLRender(SoGLRenderAction * action)154 SoDirectionalLight::GLRender(SoGLRenderAction * action)
155 {
156   if (!this->on.getValue()) return;
157 
158   SoState * state = action->getState();
159   int idx = SoGLLightIdElement::increment(state);
160 
161   if (idx < 0) {
162 #if COIN_DEBUG
163     SoDebugError::postWarning("SoDirectionalLight::GLRender",
164                               "Max # of OpenGL lights exceeded :(");
165 #endif // COIN_DEBUG
166     return;
167   }
168 
169 
170   SoLightElement::add(state, this, SoModelMatrixElement::get(state) *
171                       SoViewingMatrixElement::get(state));
172 
173   GLenum light = (GLenum) (idx + GL_LIGHT0);
174 
175   SbColor4f lightcolor(0.0f, 0.0f, 0.0f, 1.0f);
176   // disable ambient contribution from this light source
177   glLightfv(light, GL_AMBIENT, lightcolor.getValue());
178 
179   lightcolor.setRGB(this->color.getValue());
180   lightcolor *= this->intensity.getValue();
181 
182   glLightfv(light, GL_DIFFUSE, lightcolor.getValue());
183   glLightfv(light, GL_SPECULAR, lightcolor.getValue());
184 
185   // GL directional light is specified towards light source
186   SbVec3f dir = - this->direction.getValue();
187   if (dir.normalize() == 0.0f) {
188 #if COIN_DEBUG
189     SoDebugError::postWarning("SoDirectionalLight::GLRender",
190                               "Direction is a null vector.");
191 #endif // COIN_DEBUG
192   }
193   // directional when w = 0.0
194   SbVec4f dirvec(dir[0], dir[1], dir[2], 0.0f);
195   glLightfv(light, GL_POSITION, dirvec.getValue());
196 
197   glLightf(light, GL_SPOT_EXPONENT, 0.0);
198   glLightf(light, GL_SPOT_CUTOFF, 180.0);
199   glLightf(light, GL_CONSTANT_ATTENUATION, 1);
200   glLightf(light, GL_LINEAR_ATTENUATION, 0);
201   glLightf(light, GL_QUADRATIC_ATTENUATION, 0);
202 }
203 
204 // *************************************************************************
205