diff options
author | David Walter Seikel | 2013-01-13 18:54:10 +1000 |
---|---|---|
committer | David Walter Seikel | 2013-01-13 18:54:10 +1000 |
commit | 959831f4ef5a3e797f576c3de08cd65032c997ad (patch) | |
tree | e7351908be5995f0b325b2ebeaa02d5a34b82583 /libraries/irrlicht-1.8/examples/20.ManagedLights/main.cpp | |
parent | Add info about changes to Irrlicht. (diff) | |
download | SledjHamr-959831f4ef5a3e797f576c3de08cd65032c997ad.zip SledjHamr-959831f4ef5a3e797f576c3de08cd65032c997ad.tar.gz SledjHamr-959831f4ef5a3e797f576c3de08cd65032c997ad.tar.bz2 SledjHamr-959831f4ef5a3e797f576c3de08cd65032c997ad.tar.xz |
Remove damned ancient DOS line endings from Irrlicht. Hopefully I did not go overboard.
Diffstat (limited to 'libraries/irrlicht-1.8/examples/20.ManagedLights/main.cpp')
-rw-r--r-- | libraries/irrlicht-1.8/examples/20.ManagedLights/main.cpp | 772 |
1 files changed, 386 insertions, 386 deletions
diff --git a/libraries/irrlicht-1.8/examples/20.ManagedLights/main.cpp b/libraries/irrlicht-1.8/examples/20.ManagedLights/main.cpp index f67337a..3fc81a4 100644 --- a/libraries/irrlicht-1.8/examples/20.ManagedLights/main.cpp +++ b/libraries/irrlicht-1.8/examples/20.ManagedLights/main.cpp | |||
@@ -1,386 +1,386 @@ | |||
1 | /** Example 020 Managed Lights | 1 | /** Example 020 Managed Lights |
2 | 2 | ||
3 | Written by Colin MacDonald. This tutorial explains the use of the Light Manager | 3 | Written by Colin MacDonald. This tutorial explains the use of the Light Manager |
4 | of Irrlicht. It enables the use of more dynamic light sources than the actual | 4 | of Irrlicht. It enables the use of more dynamic light sources than the actual |
5 | hardware supports. Further applications of the Light Manager, such as per scene | 5 | hardware supports. Further applications of the Light Manager, such as per scene |
6 | node callbacks, are left out for simplicity of the example. | 6 | node callbacks, are left out for simplicity of the example. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <irrlicht.h> | 9 | #include <irrlicht.h> |
10 | #include "driverChoice.h" | 10 | #include "driverChoice.h" |
11 | 11 | ||
12 | using namespace irr; | 12 | using namespace irr; |
13 | using namespace core; | 13 | using namespace core; |
14 | 14 | ||
15 | #if defined(_MSC_VER) | 15 | #if defined(_MSC_VER) |
16 | #pragma comment(lib, "Irrlicht.lib") | 16 | #pragma comment(lib, "Irrlicht.lib") |
17 | #endif // MSC_VER | 17 | #endif // MSC_VER |
18 | 18 | ||
19 | /* | 19 | /* |
20 | Normally, you are limited to 8 dynamic lights per scene: this is a hardware limit. If you | 20 | Normally, you are limited to 8 dynamic lights per scene: this is a hardware limit. If you |
21 | want to use more dynamic lights in your scene, then you can register an optional light | 21 | want to use more dynamic lights in your scene, then you can register an optional light |
22 | manager that allows you to to turn lights on and off at specific point during rendering. | 22 | manager that allows you to to turn lights on and off at specific point during rendering. |
23 | You are still limited to 8 lights, but the limit is per scene node. | 23 | You are still limited to 8 lights, but the limit is per scene node. |
24 | 24 | ||
25 | This is completely optional: if you do not register a light manager, then a default | 25 | This is completely optional: if you do not register a light manager, then a default |
26 | distance-based scheme will be used to prioritise hardware lights based on their distance | 26 | distance-based scheme will be used to prioritise hardware lights based on their distance |
27 | from the active camera. | 27 | from the active camera. |
28 | 28 | ||
29 | NO_MANAGEMENT disables the light manager and shows Irrlicht's default light behaviour. | 29 | NO_MANAGEMENT disables the light manager and shows Irrlicht's default light behaviour. |
30 | The 8 lights nearest to the camera will be turned on, and other lights will be turned off. | 30 | The 8 lights nearest to the camera will be turned on, and other lights will be turned off. |
31 | In this example, this produces a funky looking but incoherent light display. | 31 | In this example, this produces a funky looking but incoherent light display. |
32 | 32 | ||
33 | LIGHTS_NEAREST_NODE shows an implementation that turns on a limited number of lights | 33 | LIGHTS_NEAREST_NODE shows an implementation that turns on a limited number of lights |
34 | per mesh scene node. If finds the 3 lights that are nearest to the node being rendered, | 34 | per mesh scene node. If finds the 3 lights that are nearest to the node being rendered, |
35 | and turns them on, turning all other lights off. This works, but as it operates on every | 35 | and turns them on, turning all other lights off. This works, but as it operates on every |
36 | light for every node, it does not scale well with many lights. The flickering you can see | 36 | light for every node, it does not scale well with many lights. The flickering you can see |
37 | in this demo is due to the lights swapping their relative positions from the cubes | 37 | in this demo is due to the lights swapping their relative positions from the cubes |
38 | (a deliberate demonstration of the limitations of this technique). | 38 | (a deliberate demonstration of the limitations of this technique). |
39 | 39 | ||
40 | LIGHTS_IN_ZONE shows a technique for turning on lights based on a 'zone'. Each empty scene | 40 | LIGHTS_IN_ZONE shows a technique for turning on lights based on a 'zone'. Each empty scene |
41 | node is considered to be the parent of a zone. When nodes are rendered, they turn off all | 41 | node is considered to be the parent of a zone. When nodes are rendered, they turn off all |
42 | lights, then find their parent 'zone' and turn on all lights that are inside that zone, i.e. | 42 | lights, then find their parent 'zone' and turn on all lights that are inside that zone, i.e. |
43 | are descendents of it in the scene graph. This produces true 'local' lighting for each cube | 43 | are descendents of it in the scene graph. This produces true 'local' lighting for each cube |
44 | in this example. You could use a similar technique to locally light all meshes in (e.g.) | 44 | in this example. You could use a similar technique to locally light all meshes in (e.g.) |
45 | a room, without the lights spilling out to other rooms. | 45 | a room, without the lights spilling out to other rooms. |
46 | 46 | ||
47 | This light manager is also an event receiver; this is purely for simplicity in this example, | 47 | This light manager is also an event receiver; this is purely for simplicity in this example, |
48 | it's neither necessary nor recommended for a real application. | 48 | it's neither necessary nor recommended for a real application. |
49 | */ | 49 | */ |
50 | class CMyLightManager : public scene::ILightManager, public IEventReceiver | 50 | class CMyLightManager : public scene::ILightManager, public IEventReceiver |
51 | { | 51 | { |
52 | typedef enum | 52 | typedef enum |
53 | { | 53 | { |
54 | NO_MANAGEMENT, | 54 | NO_MANAGEMENT, |
55 | LIGHTS_NEAREST_NODE, | 55 | LIGHTS_NEAREST_NODE, |
56 | LIGHTS_IN_ZONE | 56 | LIGHTS_IN_ZONE |
57 | } | 57 | } |
58 | LightManagementMode; | 58 | LightManagementMode; |
59 | 59 | ||
60 | LightManagementMode Mode; | 60 | LightManagementMode Mode; |
61 | LightManagementMode RequestedMode; | 61 | LightManagementMode RequestedMode; |
62 | 62 | ||
63 | // These data represent the state information that this light manager | 63 | // These data represent the state information that this light manager |
64 | // is interested in. | 64 | // is interested in. |
65 | scene::ISceneManager * SceneManager; | 65 | scene::ISceneManager * SceneManager; |
66 | core::array<scene::ISceneNode*> * SceneLightList; | 66 | core::array<scene::ISceneNode*> * SceneLightList; |
67 | scene::E_SCENE_NODE_RENDER_PASS CurrentRenderPass; | 67 | scene::E_SCENE_NODE_RENDER_PASS CurrentRenderPass; |
68 | scene::ISceneNode * CurrentSceneNode; | 68 | scene::ISceneNode * CurrentSceneNode; |
69 | 69 | ||
70 | public: | 70 | public: |
71 | CMyLightManager(scene::ISceneManager* sceneManager) | 71 | CMyLightManager(scene::ISceneManager* sceneManager) |
72 | : Mode(NO_MANAGEMENT), RequestedMode(NO_MANAGEMENT), | 72 | : Mode(NO_MANAGEMENT), RequestedMode(NO_MANAGEMENT), |
73 | SceneManager(sceneManager), SceneLightList(0), | 73 | SceneManager(sceneManager), SceneLightList(0), |
74 | CurrentRenderPass(scene::ESNRP_NONE), CurrentSceneNode(0) | 74 | CurrentRenderPass(scene::ESNRP_NONE), CurrentSceneNode(0) |
75 | { } | 75 | { } |
76 | 76 | ||
77 | // The input receiver interface, which just switches light management strategy | 77 | // The input receiver interface, which just switches light management strategy |
78 | bool OnEvent(const SEvent & event) | 78 | bool OnEvent(const SEvent & event) |
79 | { | 79 | { |
80 | bool handled = false; | 80 | bool handled = false; |
81 | 81 | ||
82 | if (event.EventType == irr::EET_KEY_INPUT_EVENT && event.KeyInput.PressedDown) | 82 | if (event.EventType == irr::EET_KEY_INPUT_EVENT && event.KeyInput.PressedDown) |
83 | { | 83 | { |
84 | handled = true; | 84 | handled = true; |
85 | switch(event.KeyInput.Key) | 85 | switch(event.KeyInput.Key) |
86 | { | 86 | { |
87 | case irr::KEY_KEY_1: | 87 | case irr::KEY_KEY_1: |
88 | RequestedMode = NO_MANAGEMENT; | 88 | RequestedMode = NO_MANAGEMENT; |
89 | break; | 89 | break; |
90 | case irr::KEY_KEY_2: | 90 | case irr::KEY_KEY_2: |
91 | RequestedMode = LIGHTS_NEAREST_NODE; | 91 | RequestedMode = LIGHTS_NEAREST_NODE; |
92 | break; | 92 | break; |
93 | case irr::KEY_KEY_3: | 93 | case irr::KEY_KEY_3: |
94 | RequestedMode = LIGHTS_IN_ZONE; | 94 | RequestedMode = LIGHTS_IN_ZONE; |
95 | break; | 95 | break; |
96 | default: | 96 | default: |
97 | handled = false; | 97 | handled = false; |
98 | break; | 98 | break; |
99 | } | 99 | } |
100 | 100 | ||
101 | if(NO_MANAGEMENT == RequestedMode) | 101 | if(NO_MANAGEMENT == RequestedMode) |
102 | SceneManager->setLightManager(0); // Show that it's safe to register the light manager | 102 | SceneManager->setLightManager(0); // Show that it's safe to register the light manager |
103 | else | 103 | else |
104 | SceneManager->setLightManager(this); | 104 | SceneManager->setLightManager(this); |
105 | } | 105 | } |
106 | 106 | ||
107 | return handled; | 107 | return handled; |
108 | } | 108 | } |
109 | 109 | ||
110 | 110 | ||
111 | // This is called before the first scene node is rendered. | 111 | // This is called before the first scene node is rendered. |
112 | virtual void OnPreRender(core::array<scene::ISceneNode*> & lightList) | 112 | virtual void OnPreRender(core::array<scene::ISceneNode*> & lightList) |
113 | { | 113 | { |
114 | // Update the mode; changing it here ensures that it's consistent throughout a render | 114 | // Update the mode; changing it here ensures that it's consistent throughout a render |
115 | Mode = RequestedMode; | 115 | Mode = RequestedMode; |
116 | 116 | ||
117 | // Store the light list. I am free to alter this list until the end of OnPostRender(). | 117 | // Store the light list. I am free to alter this list until the end of OnPostRender(). |
118 | SceneLightList = &lightList; | 118 | SceneLightList = &lightList; |
119 | } | 119 | } |
120 | 120 | ||
121 | // Called after the last scene node is rendered. | 121 | // Called after the last scene node is rendered. |
122 | virtual void OnPostRender() | 122 | virtual void OnPostRender() |
123 | { | 123 | { |
124 | // Since light management might be switched off in the event handler, we'll turn all | 124 | // Since light management might be switched off in the event handler, we'll turn all |
125 | // lights on to ensure that they are in a consistent state. You wouldn't normally have | 125 | // lights on to ensure that they are in a consistent state. You wouldn't normally have |
126 | // to do this when using a light manager, since you'd continue to do light management | 126 | // to do this when using a light manager, since you'd continue to do light management |
127 | // yourself. | 127 | // yourself. |
128 | for (u32 i = 0; i < SceneLightList->size(); i++) | 128 | for (u32 i = 0; i < SceneLightList->size(); i++) |
129 | (*SceneLightList)[i]->setVisible(true); | 129 | (*SceneLightList)[i]->setVisible(true); |
130 | } | 130 | } |
131 | 131 | ||
132 | virtual void OnRenderPassPreRender(scene::E_SCENE_NODE_RENDER_PASS renderPass) | 132 | virtual void OnRenderPassPreRender(scene::E_SCENE_NODE_RENDER_PASS renderPass) |
133 | { | 133 | { |
134 | // I don't have to do anything here except remember which render pass I am in. | 134 | // I don't have to do anything here except remember which render pass I am in. |
135 | CurrentRenderPass = renderPass; | 135 | CurrentRenderPass = renderPass; |
136 | } | 136 | } |
137 | 137 | ||
138 | virtual void OnRenderPassPostRender(scene::E_SCENE_NODE_RENDER_PASS renderPass) | 138 | virtual void OnRenderPassPostRender(scene::E_SCENE_NODE_RENDER_PASS renderPass) |
139 | { | 139 | { |
140 | // I only want solid nodes to be lit, so after the solid pass, turn all lights off. | 140 | // I only want solid nodes to be lit, so after the solid pass, turn all lights off. |
141 | if (scene::ESNRP_SOLID == renderPass) | 141 | if (scene::ESNRP_SOLID == renderPass) |
142 | { | 142 | { |
143 | for (u32 i = 0; i < SceneLightList->size(); ++i) | 143 | for (u32 i = 0; i < SceneLightList->size(); ++i) |
144 | (*SceneLightList)[i]->setVisible(false); | 144 | (*SceneLightList)[i]->setVisible(false); |
145 | } | 145 | } |
146 | } | 146 | } |
147 | 147 | ||
148 | // This is called before the specified scene node is rendered | 148 | // This is called before the specified scene node is rendered |
149 | virtual void OnNodePreRender(scene::ISceneNode* node) | 149 | virtual void OnNodePreRender(scene::ISceneNode* node) |
150 | { | 150 | { |
151 | CurrentSceneNode = node; | 151 | CurrentSceneNode = node; |
152 | 152 | ||
153 | // This light manager only considers solid objects, but you are free to manipulate | 153 | // This light manager only considers solid objects, but you are free to manipulate |
154 | // lights during any phase, depending on your requirements. | 154 | // lights during any phase, depending on your requirements. |
155 | if (scene::ESNRP_SOLID != CurrentRenderPass) | 155 | if (scene::ESNRP_SOLID != CurrentRenderPass) |
156 | return; | 156 | return; |
157 | 157 | ||
158 | // And in fact for this example, I only want to consider lighting for cube scene | 158 | // And in fact for this example, I only want to consider lighting for cube scene |
159 | // nodes. You will probably want to deal with lighting for (at least) mesh / | 159 | // nodes. You will probably want to deal with lighting for (at least) mesh / |
160 | // animated mesh scene nodes as well. | 160 | // animated mesh scene nodes as well. |
161 | if (node->getType() != scene::ESNT_CUBE) | 161 | if (node->getType() != scene::ESNT_CUBE) |
162 | return; | 162 | return; |
163 | 163 | ||
164 | if (LIGHTS_NEAREST_NODE == Mode) | 164 | if (LIGHTS_NEAREST_NODE == Mode) |
165 | { | 165 | { |
166 | // This is a naive implementation that prioritises every light in the scene | 166 | // This is a naive implementation that prioritises every light in the scene |
167 | // by its proximity to the node being rendered. This produces some flickering | 167 | // by its proximity to the node being rendered. This produces some flickering |
168 | // when lights orbit closer to a cube than its 'zone' lights. | 168 | // when lights orbit closer to a cube than its 'zone' lights. |
169 | const vector3df nodePosition = node->getAbsolutePosition(); | 169 | const vector3df nodePosition = node->getAbsolutePosition(); |
170 | 170 | ||
171 | // Sort the light list by prioritising them based on their distance from the node | 171 | // Sort the light list by prioritising them based on their distance from the node |
172 | // that's about to be rendered. | 172 | // that's about to be rendered. |
173 | array<LightDistanceElement> sortingArray; | 173 | array<LightDistanceElement> sortingArray; |
174 | sortingArray.reallocate(SceneLightList->size()); | 174 | sortingArray.reallocate(SceneLightList->size()); |
175 | 175 | ||
176 | u32 i; | 176 | u32 i; |
177 | for(i = 0; i < SceneLightList->size(); ++i) | 177 | for(i = 0; i < SceneLightList->size(); ++i) |
178 | { | 178 | { |
179 | scene::ISceneNode* lightNode = (*SceneLightList)[i]; | 179 | scene::ISceneNode* lightNode = (*SceneLightList)[i]; |
180 | const f64 distance = lightNode->getAbsolutePosition().getDistanceFromSQ(nodePosition); | 180 | const f64 distance = lightNode->getAbsolutePosition().getDistanceFromSQ(nodePosition); |
181 | sortingArray.push_back(LightDistanceElement(lightNode, distance)); | 181 | sortingArray.push_back(LightDistanceElement(lightNode, distance)); |
182 | } | 182 | } |
183 | 183 | ||
184 | sortingArray.sort(); | 184 | sortingArray.sort(); |
185 | 185 | ||
186 | // The list is now sorted by proximity to the node. | 186 | // The list is now sorted by proximity to the node. |
187 | // Turn on the three nearest lights, and turn the others off. | 187 | // Turn on the three nearest lights, and turn the others off. |
188 | for(i = 0; i < sortingArray.size(); ++i) | 188 | for(i = 0; i < sortingArray.size(); ++i) |
189 | sortingArray[i].node->setVisible(i < 3); | 189 | sortingArray[i].node->setVisible(i < 3); |
190 | } | 190 | } |
191 | else if(LIGHTS_IN_ZONE == Mode) | 191 | else if(LIGHTS_IN_ZONE == Mode) |
192 | { | 192 | { |
193 | // Empty scene nodes are used to represent 'zones'. For each solid mesh that | 193 | // Empty scene nodes are used to represent 'zones'. For each solid mesh that |
194 | // is being rendered, turn off all lights, then find its 'zone' parent, and turn | 194 | // is being rendered, turn off all lights, then find its 'zone' parent, and turn |
195 | // on all lights that are found under that node in the scene graph. | 195 | // on all lights that are found under that node in the scene graph. |
196 | // This is a general purpose algorithm that doesn't use any special | 196 | // This is a general purpose algorithm that doesn't use any special |
197 | // knowledge of how this particular scene graph is organised. | 197 | // knowledge of how this particular scene graph is organised. |
198 | for (u32 i = 0; i < SceneLightList->size(); ++i) | 198 | for (u32 i = 0; i < SceneLightList->size(); ++i) |
199 | { | 199 | { |
200 | if ((*SceneLightList)[i]->getType() != scene::ESNT_LIGHT) | 200 | if ((*SceneLightList)[i]->getType() != scene::ESNT_LIGHT) |
201 | continue; | 201 | continue; |
202 | scene::ILightSceneNode* lightNode = static_cast<scene::ILightSceneNode*>((*SceneLightList)[i]); | 202 | scene::ILightSceneNode* lightNode = static_cast<scene::ILightSceneNode*>((*SceneLightList)[i]); |
203 | video::SLight & lightData = lightNode->getLightData(); | 203 | video::SLight & lightData = lightNode->getLightData(); |
204 | 204 | ||
205 | if (video::ELT_DIRECTIONAL != lightData.Type) | 205 | if (video::ELT_DIRECTIONAL != lightData.Type) |
206 | lightNode->setVisible(false); | 206 | lightNode->setVisible(false); |
207 | } | 207 | } |
208 | 208 | ||
209 | scene::ISceneNode * parentZone = findZone(node); | 209 | scene::ISceneNode * parentZone = findZone(node); |
210 | if (parentZone) | 210 | if (parentZone) |
211 | turnOnZoneLights(parentZone); | 211 | turnOnZoneLights(parentZone); |
212 | } | 212 | } |
213 | } | 213 | } |
214 | 214 | ||
215 | // Called after the specified scene node is rendered | 215 | // Called after the specified scene node is rendered |
216 | virtual void OnNodePostRender(scene::ISceneNode* node) | 216 | virtual void OnNodePostRender(scene::ISceneNode* node) |
217 | { | 217 | { |
218 | // I don't need to do any light management after individual node rendering. | 218 | // I don't need to do any light management after individual node rendering. |
219 | } | 219 | } |
220 | 220 | ||
221 | private: | 221 | private: |
222 | 222 | ||
223 | // Find the empty scene node that is the parent of the specified node | 223 | // Find the empty scene node that is the parent of the specified node |
224 | scene::ISceneNode * findZone(scene::ISceneNode * node) | 224 | scene::ISceneNode * findZone(scene::ISceneNode * node) |
225 | { | 225 | { |
226 | if (!node) | 226 | if (!node) |
227 | return 0; | 227 | return 0; |
228 | 228 | ||
229 | if (node->getType() == scene::ESNT_EMPTY) | 229 | if (node->getType() == scene::ESNT_EMPTY) |
230 | return node; | 230 | return node; |
231 | 231 | ||
232 | return findZone(node->getParent()); | 232 | return findZone(node->getParent()); |
233 | } | 233 | } |
234 | 234 | ||
235 | // Turn on all lights that are children (directly or indirectly) of the | 235 | // Turn on all lights that are children (directly or indirectly) of the |
236 | // specified scene node. | 236 | // specified scene node. |
237 | void turnOnZoneLights(scene::ISceneNode * node) | 237 | void turnOnZoneLights(scene::ISceneNode * node) |
238 | { | 238 | { |
239 | core::list<scene::ISceneNode*> const & children = node->getChildren(); | 239 | core::list<scene::ISceneNode*> const & children = node->getChildren(); |
240 | for (core::list<scene::ISceneNode*>::ConstIterator child = children.begin(); | 240 | for (core::list<scene::ISceneNode*>::ConstIterator child = children.begin(); |
241 | child != children.end(); ++child) | 241 | child != children.end(); ++child) |
242 | { | 242 | { |
243 | if ((*child)->getType() == scene::ESNT_LIGHT) | 243 | if ((*child)->getType() == scene::ESNT_LIGHT) |
244 | (*child)->setVisible(true); | 244 | (*child)->setVisible(true); |
245 | else // Assume that lights don't have any children that are also lights | 245 | else // Assume that lights don't have any children that are also lights |
246 | turnOnZoneLights(*child); | 246 | turnOnZoneLights(*child); |
247 | } | 247 | } |
248 | } | 248 | } |
249 | 249 | ||
250 | 250 | ||
251 | // A utility class to aid in sorting scene nodes into a distance order | 251 | // A utility class to aid in sorting scene nodes into a distance order |
252 | class LightDistanceElement | 252 | class LightDistanceElement |
253 | { | 253 | { |
254 | public: | 254 | public: |
255 | LightDistanceElement() {}; | 255 | LightDistanceElement() {}; |
256 | 256 | ||
257 | LightDistanceElement(scene::ISceneNode* n, f64 d) | 257 | LightDistanceElement(scene::ISceneNode* n, f64 d) |
258 | : node(n), distance(d) { } | 258 | : node(n), distance(d) { } |
259 | 259 | ||
260 | scene::ISceneNode* node; | 260 | scene::ISceneNode* node; |
261 | f64 distance; | 261 | f64 distance; |
262 | 262 | ||
263 | // Lower distance elements are sorted to the start of the array | 263 | // Lower distance elements are sorted to the start of the array |
264 | bool operator < (const LightDistanceElement& other) const | 264 | bool operator < (const LightDistanceElement& other) const |
265 | { | 265 | { |
266 | return (distance < other.distance); | 266 | return (distance < other.distance); |
267 | } | 267 | } |
268 | }; | 268 | }; |
269 | }; | 269 | }; |
270 | 270 | ||
271 | 271 | ||
272 | /* | 272 | /* |
273 | */ | 273 | */ |
274 | int main(int argumentCount, char * argumentValues[]) | 274 | int main(int argumentCount, char * argumentValues[]) |
275 | { | 275 | { |
276 | // ask user for driver | 276 | // ask user for driver |
277 | video::E_DRIVER_TYPE driverType=driverChoiceConsole(); | 277 | video::E_DRIVER_TYPE driverType=driverChoiceConsole(); |
278 | if (driverType==video::EDT_COUNT) | 278 | if (driverType==video::EDT_COUNT) |
279 | return 1; | 279 | return 1; |
280 | 280 | ||
281 | IrrlichtDevice *device = createDevice(driverType, | 281 | IrrlichtDevice *device = createDevice(driverType, |
282 | dimension2d<u32>(640, 480), 32); | 282 | dimension2d<u32>(640, 480), 32); |
283 | 283 | ||
284 | if(!device) | 284 | if(!device) |
285 | return -1; | 285 | return -1; |
286 | 286 | ||
287 | f32 const lightRadius = 60.f; // Enough to reach the far side of each 'zone' | 287 | f32 const lightRadius = 60.f; // Enough to reach the far side of each 'zone' |
288 | 288 | ||
289 | video::IVideoDriver* driver = device->getVideoDriver(); | 289 | video::IVideoDriver* driver = device->getVideoDriver(); |
290 | scene::ISceneManager* smgr = device->getSceneManager(); | 290 | scene::ISceneManager* smgr = device->getSceneManager(); |
291 | gui::IGUIEnvironment* guienv = device->getGUIEnvironment(); | 291 | gui::IGUIEnvironment* guienv = device->getGUIEnvironment(); |
292 | 292 | ||
293 | gui::IGUISkin* skin = guienv->getSkin(); | 293 | gui::IGUISkin* skin = guienv->getSkin(); |
294 | if (skin) | 294 | if (skin) |
295 | { | 295 | { |
296 | skin->setColor(gui::EGDC_BUTTON_TEXT, video::SColor(255, 255, 255, 255)); | 296 | skin->setColor(gui::EGDC_BUTTON_TEXT, video::SColor(255, 255, 255, 255)); |
297 | gui::IGUIFont* font = guienv->getFont("../../media/fontlucida.png"); | 297 | gui::IGUIFont* font = guienv->getFont("../../media/fontlucida.png"); |
298 | if(font) | 298 | if(font) |
299 | skin->setFont(font); | 299 | skin->setFont(font); |
300 | } | 300 | } |
301 | 301 | ||
302 | guienv->addStaticText(L"1 - No light management", core::rect<s32>(10,10,200,30)); | 302 | guienv->addStaticText(L"1 - No light management", core::rect<s32>(10,10,200,30)); |
303 | guienv->addStaticText(L"2 - Closest 3 lights", core::rect<s32>(10,30,200,50)); | 303 | guienv->addStaticText(L"2 - Closest 3 lights", core::rect<s32>(10,30,200,50)); |
304 | guienv->addStaticText(L"3 - Lights in zone", core::rect<s32>(10,50,200,70)); | 304 | guienv->addStaticText(L"3 - Lights in zone", core::rect<s32>(10,50,200,70)); |
305 | 305 | ||
306 | /* | 306 | /* |
307 | Add several "zones". You could use this technique to light individual rooms, for example. | 307 | Add several "zones". You could use this technique to light individual rooms, for example. |
308 | */ | 308 | */ |
309 | for(f32 zoneX = -100.f; zoneX <= 100.f; zoneX += 50.f) | 309 | for(f32 zoneX = -100.f; zoneX <= 100.f; zoneX += 50.f) |
310 | for(f32 zoneY = -60.f; zoneY <= 60.f; zoneY += 60.f) | 310 | for(f32 zoneY = -60.f; zoneY <= 60.f; zoneY += 60.f) |
311 | { | 311 | { |
312 | // Start with an empty scene node, which we will use to represent a zone. | 312 | // Start with an empty scene node, which we will use to represent a zone. |
313 | scene::ISceneNode * zoneRoot = smgr->addEmptySceneNode(); | 313 | scene::ISceneNode * zoneRoot = smgr->addEmptySceneNode(); |
314 | zoneRoot->setPosition(vector3df(zoneX, zoneY, 0)); | 314 | zoneRoot->setPosition(vector3df(zoneX, zoneY, 0)); |
315 | 315 | ||
316 | // Each zone contains a rotating cube | 316 | // Each zone contains a rotating cube |
317 | scene::IMeshSceneNode * node = smgr->addCubeSceneNode(15, zoneRoot); | 317 | scene::IMeshSceneNode * node = smgr->addCubeSceneNode(15, zoneRoot); |
318 | scene::ISceneNodeAnimator * rotation = smgr->createRotationAnimator(vector3df(0.25f, 0.5f, 0.75f)); | 318 | scene::ISceneNodeAnimator * rotation = smgr->createRotationAnimator(vector3df(0.25f, 0.5f, 0.75f)); |
319 | node->addAnimator(rotation); | 319 | node->addAnimator(rotation); |
320 | rotation->drop(); | 320 | rotation->drop(); |
321 | 321 | ||
322 | // And each cube has three lights attached to it. The lights are attached to billboards so | 322 | // And each cube has three lights attached to it. The lights are attached to billboards so |
323 | // that we can see where they are. The billboards are attached to the cube, so that the | 323 | // that we can see where they are. The billboards are attached to the cube, so that the |
324 | // lights are indirect descendents of the same empty scene node as the cube. | 324 | // lights are indirect descendents of the same empty scene node as the cube. |
325 | scene::IBillboardSceneNode * billboard = smgr->addBillboardSceneNode(node); | 325 | scene::IBillboardSceneNode * billboard = smgr->addBillboardSceneNode(node); |
326 | billboard->setPosition(vector3df(0, -14, 30)); | 326 | billboard->setPosition(vector3df(0, -14, 30)); |
327 | billboard->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR ); | 327 | billboard->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR ); |
328 | billboard->setMaterialTexture(0, driver->getTexture("../../media/particle.bmp")); | 328 | billboard->setMaterialTexture(0, driver->getTexture("../../media/particle.bmp")); |
329 | billboard->setMaterialFlag(video::EMF_LIGHTING, false); | 329 | billboard->setMaterialFlag(video::EMF_LIGHTING, false); |
330 | smgr->addLightSceneNode(billboard, vector3df(0, 0, 0), video::SColorf(1, 0, 0), lightRadius); | 330 | smgr->addLightSceneNode(billboard, vector3df(0, 0, 0), video::SColorf(1, 0, 0), lightRadius); |
331 | 331 | ||
332 | billboard = smgr->addBillboardSceneNode(node); | 332 | billboard = smgr->addBillboardSceneNode(node); |
333 | billboard->setPosition(vector3df(-21, -14, -21)); | 333 | billboard->setPosition(vector3df(-21, -14, -21)); |
334 | billboard->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR ); | 334 | billboard->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR ); |
335 | billboard->setMaterialTexture(0, driver->getTexture("../../media/particle.bmp")); | 335 | billboard->setMaterialTexture(0, driver->getTexture("../../media/particle.bmp")); |
336 | billboard->setMaterialFlag(video::EMF_LIGHTING, false); | 336 | billboard->setMaterialFlag(video::EMF_LIGHTING, false); |
337 | smgr->addLightSceneNode(billboard, vector3df(0, 0, 0), video::SColorf(0, 1, 0), lightRadius); | 337 | smgr->addLightSceneNode(billboard, vector3df(0, 0, 0), video::SColorf(0, 1, 0), lightRadius); |
338 | 338 | ||
339 | billboard = smgr->addBillboardSceneNode(node); | 339 | billboard = smgr->addBillboardSceneNode(node); |
340 | billboard->setPosition(vector3df(21, -14, -21)); | 340 | billboard->setPosition(vector3df(21, -14, -21)); |
341 | billboard->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR ); | 341 | billboard->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR ); |
342 | billboard->setMaterialTexture(0, driver->getTexture("../../media/particle.bmp")); | 342 | billboard->setMaterialTexture(0, driver->getTexture("../../media/particle.bmp")); |
343 | billboard->setMaterialFlag(video::EMF_LIGHTING, false); | 343 | billboard->setMaterialFlag(video::EMF_LIGHTING, false); |
344 | smgr->addLightSceneNode(billboard, vector3df(0, 0, 0), video::SColorf(0, 0, 1), lightRadius); | 344 | smgr->addLightSceneNode(billboard, vector3df(0, 0, 0), video::SColorf(0, 0, 1), lightRadius); |
345 | 345 | ||
346 | // Each cube also has a smaller cube rotating around it, to show that the cubes are being | 346 | // Each cube also has a smaller cube rotating around it, to show that the cubes are being |
347 | // lit by the lights in their 'zone', not just lights that are their direct children. | 347 | // lit by the lights in their 'zone', not just lights that are their direct children. |
348 | node = smgr->addCubeSceneNode(5, node); | 348 | node = smgr->addCubeSceneNode(5, node); |
349 | node->setPosition(vector3df(0, 21, 0)); | 349 | node->setPosition(vector3df(0, 21, 0)); |
350 | } | 350 | } |
351 | 351 | ||
352 | smgr->addCameraSceneNode(0, vector3df(0,0,-130), vector3df(0,0,0)); | 352 | smgr->addCameraSceneNode(0, vector3df(0,0,-130), vector3df(0,0,0)); |
353 | 353 | ||
354 | CMyLightManager * myLightManager = new CMyLightManager(smgr); | 354 | CMyLightManager * myLightManager = new CMyLightManager(smgr); |
355 | smgr->setLightManager(0); // This is the default: we won't do light management until told to do it. | 355 | smgr->setLightManager(0); // This is the default: we won't do light management until told to do it. |
356 | device->setEventReceiver(myLightManager); | 356 | device->setEventReceiver(myLightManager); |
357 | 357 | ||
358 | int lastFps = -1; | 358 | int lastFps = -1; |
359 | 359 | ||
360 | while(device->run()) | 360 | while(device->run()) |
361 | { | 361 | { |
362 | driver->beginScene(true, true, video::SColor(255,100,101,140)); | 362 | driver->beginScene(true, true, video::SColor(255,100,101,140)); |
363 | smgr->drawAll(); | 363 | smgr->drawAll(); |
364 | guienv->drawAll(); | 364 | guienv->drawAll(); |
365 | driver->endScene(); | 365 | driver->endScene(); |
366 | 366 | ||
367 | int fps = driver->getFPS(); | 367 | int fps = driver->getFPS(); |
368 | if(fps != lastFps) | 368 | if(fps != lastFps) |
369 | { | 369 | { |
370 | lastFps = fps; | 370 | lastFps = fps; |
371 | core::stringw str = L"Managed Lights ["; | 371 | core::stringw str = L"Managed Lights ["; |
372 | str += driver->getName(); | 372 | str += driver->getName(); |
373 | str += "] FPS:"; | 373 | str += "] FPS:"; |
374 | str += fps; | 374 | str += fps; |
375 | device->setWindowCaption(str.c_str()); | 375 | device->setWindowCaption(str.c_str()); |
376 | } | 376 | } |
377 | } | 377 | } |
378 | 378 | ||
379 | myLightManager->drop(); // Drop my implicit reference | 379 | myLightManager->drop(); // Drop my implicit reference |
380 | device->drop(); | 380 | device->drop(); |
381 | return 0; | 381 | return 0; |
382 | } | 382 | } |
383 | 383 | ||
384 | /* | 384 | /* |
385 | **/ | 385 | **/ |
386 | 386 | ||