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