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 SoShadowDirectionalLight SoShadowDirectionalLight.h Inventor/annex/FXViz/nodes/SoShadowDirectionalLight.h
35   \brief The SoShadowDirectionalLight class is a node for setting up a directional light which casts shadows.
36 
37   Directional lights usually affect everything, but since it's not
38   always feasible to use one shadow map for the entire scene
39   graph. This node has some extra features to work around this.
40 
41   It calculates the intersection between the current view volume and
42   either the scene bounding box, or the bounding box provided in this
43   node.  The shadows are only calculated for this volume. This means
44   that you'll get more detailed shadows as you zoom in on items in the
45   scene graph.
46 
47   In addition, you can set the maximum distance from the camera which
48   will be shaded with shadows. Think of this a new far plane for the
49   camera which only affects shadows.
50 
51   As with SoShadowSpotLight, it's possible to optimize further by
52   setting your own shadow caster scene graph in the shadowMapScene
53   field.
54 
55   The example scene graph below demonstrates how you can use this node
56   to create shadows on a large number of objects, and still get decent
57   precision when zooming in. To further reduce the volume covered by
58   the shadowmap, you can set \a maxShadowDistance to some number > 0.
59   This is the distance from the camera where shadows will be visible.
60 
61   \code
62 
63   DirectionalLight {
64      direction 0 0 -1
65      intensity 0.2
66   }
67 
68   ShadowGroup {
69     quality 1 # to get per pixel lighting
70     precision 1
71 
72     ShadowDirectionalLight {
73       direction 1 1 -1
74       intensity 0.8
75       # enable this to reduce the shadow view distance
76       # maxShadowDistance 200
77     }
78 
79     # 900 cubes spaced out over a fairly large area
80     Array {
81       origin CENTER
82       numElements1 30
83       numElements2 30
84       numElements3 1
85       separation1 20 0 0
86       separation2 0 20 0
87       separation3 0 0 0
88 
89       Material { diffuseColor 1 0 0 specularColor 1 1 1 }
90       Cube { width 4 height 4 depth 4 }
91     }
92 
93     # a chess board
94     Coordinate3 { point [ -400 -400 -3, 400 -400 -3, 400 400 -3, -400 400 -3 ] }
95     Material { specularColor 1 1 1 shininess 0.9 }
96     Complexity { textureQuality 0.1 }
97     Texture2 { image 2 2 3 0xffffff 0x225588 0x225588 0xffffff }
98     Texture2Transform { scaleFactor 20 20 }
99     FaceSet { numVertices 4 }
100   }
101   \endcode
102 
103   \since Coin 3.0
104 */
105 
106 /*!
107   \var SoSFNode SoShadowDirectionalLight::shadowMapScene
108 
109   The shadow map scene graph. If this is NULL (the default), the node
110   will behave as a normal SoDirectionalLight node.
111 
112 */
113 
114 /*!
115   \var SoSFFloat SoShadowDirectionalLight::maxShadowDistance
116 
117   The maximum distance (from the camera) that we'll see shadows from this light source.
118 */
119 
120 /*!
121   \var SoSFVec3f SoShadowDirectionalLight::bboxCenter
122 
123   Can be used to specify the volume that should be used for
124   calculating the resulting shadow volume.
125 */
126 
127 /*!
128   \var SoSFVec3f SoShadowDirectionalLight::bboxSize
129 
130   Can be used to specify the volume that should be used for
131   calculating the resulting shadow volume.
132 */
133 
134 // *************************************************************************
135 
136 #include <Inventor/annex/FXViz/nodes/SoShadowDirectionalLight.h>
137 
138 #include <cstdio>
139 #include <Inventor/actions/SoGLRenderAction.h>
140 
141 #include "nodes/SoSubNodeP.h"
142 
143 // *************************************************************************
144 
145 
146 SO_NODE_SOURCE(SoShadowDirectionalLight);
147 
148 /*!
149   Constructor.
150 */
SoShadowDirectionalLight(void)151 SoShadowDirectionalLight::SoShadowDirectionalLight(void)
152 {
153   SO_NODE_INTERNAL_CONSTRUCTOR(SoShadowDirectionalLight);
154   SO_NODE_ADD_FIELD(shadowMapScene, (NULL));
155   SO_NODE_ADD_FIELD(maxShadowDistance, (-1.0f));
156   SO_NODE_ADD_FIELD(bboxCenter, (0.0f, 0.0f, 0.0f));
157   SO_NODE_ADD_FIELD(bboxSize, (-1.0f, -1.0f, -1.0f));
158 }
159 
160 /*!
161   Destructor.
162 */
~SoShadowDirectionalLight()163 SoShadowDirectionalLight::~SoShadowDirectionalLight()
164 {
165 }
166 
167 // Doc from superclass.
168 void
initClass(void)169 SoShadowDirectionalLight::initClass(void)
170 {
171   SO_NODE_INTERNAL_INIT_CLASS(SoShadowDirectionalLight, SO_FROM_COIN_4_0);
172 }
173 
174 // Doc from superclass.
175 void
GLRender(SoGLRenderAction * action)176 SoShadowDirectionalLight::GLRender(SoGLRenderAction * action)
177 {
178   inherited::GLRender(action);
179 }
180 
181 #ifdef COIN_TEST_SUITE
182 
BOOST_AUTO_TEST_CASE(initialized)183 BOOST_AUTO_TEST_CASE(initialized)
184 {
185   SoShadowDirectionalLight * node = new SoShadowDirectionalLight;
186   assert(node);
187   node->ref();
188   BOOST_CHECK_MESSAGE(node->getTypeId() != SoType::badType(),
189                       "missing class initialization");
190   node->unref();
191 }
192 
193 #endif // COIN_TEST_SUITE
194