diff options
Diffstat (limited to '')
-rw-r--r-- | libraries/irrlicht-1.8.1/examples/08.SpecialFX/main.cpp | 308 |
1 files changed, 308 insertions, 0 deletions
diff --git a/libraries/irrlicht-1.8.1/examples/08.SpecialFX/main.cpp b/libraries/irrlicht-1.8.1/examples/08.SpecialFX/main.cpp new file mode 100644 index 0000000..d8f32f7 --- /dev/null +++ b/libraries/irrlicht-1.8.1/examples/08.SpecialFX/main.cpp | |||
@@ -0,0 +1,308 @@ | |||
1 | /** Example 008 SpecialFX | ||
2 | |||
3 | This tutorials describes how to do special effects. It shows how to use stencil | ||
4 | buffer shadows, the particle system, billboards, dynamic light, and the water | ||
5 | surface scene node. | ||
6 | |||
7 | We start like in some tutorials before. Please note that this time, the | ||
8 | 'shadows' flag in createDevice() is set to true, for we want to have a dynamic | ||
9 | shadow casted from an animated character. If this example runs too slow, | ||
10 | set it to false. The Irrlicht Engine checks if your hardware doesn't support | ||
11 | the stencil buffer, and disables shadows by itself, but just in case the demo | ||
12 | runs slow on your hardware. | ||
13 | */ | ||
14 | |||
15 | #include <irrlicht.h> | ||
16 | #include <iostream> | ||
17 | #include "driverChoice.h" | ||
18 | |||
19 | using namespace irr; | ||
20 | |||
21 | #ifdef _MSC_VER | ||
22 | #pragma comment(lib, "Irrlicht.lib") | ||
23 | #endif | ||
24 | |||
25 | int main() | ||
26 | { | ||
27 | // ask if user would like shadows | ||
28 | char i; | ||
29 | printf("Please press 'y' if you want to use realtime shadows.\n"); | ||
30 | |||
31 | std::cin >> i; | ||
32 | |||
33 | const bool shadows = (i == 'y'); | ||
34 | |||
35 | // ask user for driver | ||
36 | video::E_DRIVER_TYPE driverType=driverChoiceConsole(); | ||
37 | if (driverType==video::EDT_COUNT) | ||
38 | return 1; | ||
39 | |||
40 | |||
41 | /* | ||
42 | Create device and exit if creation failed. We make the stencil flag | ||
43 | optional to avoid slow screen modes for runs without shadows. | ||
44 | */ | ||
45 | |||
46 | IrrlichtDevice *device = | ||
47 | createDevice(driverType, core::dimension2d<u32>(640, 480), | ||
48 | 16, false, shadows); | ||
49 | |||
50 | if (device == 0) | ||
51 | return 1; // could not create selected driver. | ||
52 | |||
53 | video::IVideoDriver* driver = device->getVideoDriver(); | ||
54 | scene::ISceneManager* smgr = device->getSceneManager(); | ||
55 | |||
56 | /* | ||
57 | For our environment, we load a .3ds file. It is a small room I modelled | ||
58 | with Anim8or and exported into the 3ds format because the Irrlicht | ||
59 | Engine does not support the .an8 format. I am a very bad 3d graphic | ||
60 | artist, and so the texture mapping is not very nice in this model. | ||
61 | Luckily I am a better programmer than artist, and so the Irrlicht | ||
62 | Engine is able to create a cool texture mapping for me: Just use the | ||
63 | mesh manipulator and create a planar texture mapping for the mesh. If | ||
64 | you want to see the mapping I made with Anim8or, uncomment this line. I | ||
65 | also did not figure out how to set the material right in Anim8or, it | ||
66 | has a specular light color which I don't really like. I'll switch it | ||
67 | off too with this code. | ||
68 | */ | ||
69 | |||
70 | scene::IAnimatedMesh* mesh = smgr->getMesh("../../media/room.3ds"); | ||
71 | |||
72 | smgr->getMeshManipulator()->makePlanarTextureMapping(mesh->getMesh(0), 0.004f); | ||
73 | |||
74 | scene::ISceneNode* node = 0; | ||
75 | |||
76 | node = smgr->addAnimatedMeshSceneNode(mesh); | ||
77 | node->setMaterialTexture(0, driver->getTexture("../../media/wall.jpg")); | ||
78 | node->getMaterial(0).SpecularColor.set(0,0,0,0); | ||
79 | |||
80 | /* | ||
81 | Now, for the first special effect: Animated water. It works like this: | ||
82 | The WaterSurfaceSceneNode takes a mesh as input and makes it wave like | ||
83 | a water surface. And if we let this scene node use a nice material like | ||
84 | the EMT_REFLECTION_2_LAYER, it looks really cool. We are doing this | ||
85 | with the next few lines of code. As input mesh, we create a hill plane | ||
86 | mesh, without hills. But any other mesh could be used for this, you | ||
87 | could even use the room.3ds (which would look really strange) if you | ||
88 | want to. | ||
89 | */ | ||
90 | |||
91 | mesh = smgr->addHillPlaneMesh( "myHill", | ||
92 | core::dimension2d<f32>(20,20), | ||
93 | core::dimension2d<u32>(40,40), 0, 0, | ||
94 | core::dimension2d<f32>(0,0), | ||
95 | core::dimension2d<f32>(10,10)); | ||
96 | |||
97 | node = smgr->addWaterSurfaceSceneNode(mesh->getMesh(0), 3.0f, 300.0f, 30.0f); | ||
98 | node->setPosition(core::vector3df(0,7,0)); | ||
99 | |||
100 | node->setMaterialTexture(0, driver->getTexture("../../media/stones.jpg")); | ||
101 | node->setMaterialTexture(1, driver->getTexture("../../media/water.jpg")); | ||
102 | |||
103 | node->setMaterialType(video::EMT_REFLECTION_2_LAYER); | ||
104 | |||
105 | /* | ||
106 | The second special effect is very basic, I bet you saw it already in | ||
107 | some Irrlicht Engine demos: A transparent billboard combined with a | ||
108 | dynamic light. We simply create a light scene node, let it fly around, | ||
109 | and to make it look more cool, we attach a billboard scene node to it. | ||
110 | */ | ||
111 | |||
112 | // create light | ||
113 | |||
114 | node = smgr->addLightSceneNode(0, core::vector3df(0,0,0), | ||
115 | video::SColorf(1.0f, 0.6f, 0.7f, 1.0f), 800.0f); | ||
116 | scene::ISceneNodeAnimator* anim = 0; | ||
117 | anim = smgr->createFlyCircleAnimator (core::vector3df(0,150,0),250.0f); | ||
118 | node->addAnimator(anim); | ||
119 | anim->drop(); | ||
120 | |||
121 | // attach billboard to light | ||
122 | |||
123 | node = smgr->addBillboardSceneNode(node, core::dimension2d<f32>(50, 50)); | ||
124 | node->setMaterialFlag(video::EMF_LIGHTING, false); | ||
125 | node->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR); | ||
126 | node->setMaterialTexture(0, driver->getTexture("../../media/particlewhite.bmp")); | ||
127 | |||
128 | /* | ||
129 | The next special effect is a lot more interesting: A particle system. | ||
130 | The particle system in the Irrlicht Engine is quite modular and | ||
131 | extensible, but yet easy to use. There is a particle system scene node | ||
132 | into which you can put a particle emitter, which makes particles come out | ||
133 | of nothing. These emitters are quite flexible and usually have lots of | ||
134 | parameters like direction, amount, and color of the particles they | ||
135 | create. | ||
136 | |||
137 | There are different emitters, for example a point emitter which lets | ||
138 | particles pop out at a fixed point. If the particle emitters available | ||
139 | in the engine are not enough for you, you can easily create your own | ||
140 | ones, you'll simply have to create a class derived from the | ||
141 | IParticleEmitter interface and attach it to the particle system using | ||
142 | setEmitter(). In this example we create a box particle emitter, which | ||
143 | creates particles randomly inside a box. The parameters define the box, | ||
144 | direction of the particles, minimal and maximal new particles per | ||
145 | second, color, and minimal and maximal lifetime of the particles. | ||
146 | |||
147 | Because only with emitters particle system would be a little bit | ||
148 | boring, there are particle affectors which modify particles while | ||
149 | they fly around. Affectors can be added to a particle system for | ||
150 | simulating additional effects like gravity or wind. | ||
151 | The particle affector we use in this example is an affector which | ||
152 | modifies the color of the particles: It lets them fade out. Like the | ||
153 | particle emitters, additional particle affectors can also be | ||
154 | implemented by you, simply derive a class from IParticleAffector and | ||
155 | add it with addAffector(). | ||
156 | |||
157 | After we set a nice material to the particle system, we have a cool | ||
158 | looking camp fire. By adjusting material, texture, particle emitter, | ||
159 | and affector parameters, it is also easily possible to create smoke, | ||
160 | rain, explosions, snow, and so on. | ||
161 | */ | ||
162 | |||
163 | // create a particle system | ||
164 | |||
165 | scene::IParticleSystemSceneNode* ps = | ||
166 | smgr->addParticleSystemSceneNode(false); | ||
167 | |||
168 | scene::IParticleEmitter* em = ps->createBoxEmitter( | ||
169 | core::aabbox3d<f32>(-7,0,-7,7,1,7), // emitter size | ||
170 | core::vector3df(0.0f,0.06f,0.0f), // initial direction | ||
171 | 80,100, // emit rate | ||
172 | video::SColor(0,255,255,255), // darkest color | ||
173 | video::SColor(0,255,255,255), // brightest color | ||
174 | 800,2000,0, // min and max age, angle | ||
175 | core::dimension2df(10.f,10.f), // min size | ||
176 | core::dimension2df(20.f,20.f)); // max size | ||
177 | |||
178 | ps->setEmitter(em); // this grabs the emitter | ||
179 | em->drop(); // so we can drop it here without deleting it | ||
180 | |||
181 | scene::IParticleAffector* paf = ps->createFadeOutParticleAffector(); | ||
182 | |||
183 | ps->addAffector(paf); // same goes for the affector | ||
184 | paf->drop(); | ||
185 | |||
186 | ps->setPosition(core::vector3df(-70,60,40)); | ||
187 | ps->setScale(core::vector3df(2,2,2)); | ||
188 | ps->setMaterialFlag(video::EMF_LIGHTING, false); | ||
189 | ps->setMaterialFlag(video::EMF_ZWRITE_ENABLE, false); | ||
190 | ps->setMaterialTexture(0, driver->getTexture("../../media/fire.bmp")); | ||
191 | ps->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR); | ||
192 | |||
193 | /* | ||
194 | Next we add a volumetric light node, which adds a glowing fake area light to | ||
195 | the scene. Like with the billboards and particle systems we also assign a | ||
196 | texture for the desired effect, though this time we'll use a texture animator | ||
197 | to create the illusion of a magical glowing area effect. | ||
198 | */ | ||
199 | scene::IVolumeLightSceneNode * n = smgr->addVolumeLightSceneNode(0, -1, | ||
200 | 32, // Subdivisions on U axis | ||
201 | 32, // Subdivisions on V axis | ||
202 | video::SColor(0, 255, 255, 255), // foot color | ||
203 | video::SColor(0, 0, 0, 0)); // tail color | ||
204 | |||
205 | if (n) | ||
206 | { | ||
207 | n->setScale(core::vector3df(56.0f, 56.0f, 56.0f)); | ||
208 | n->setPosition(core::vector3df(-120,50,40)); | ||
209 | |||
210 | // load textures for animation | ||
211 | core::array<video::ITexture*> textures; | ||
212 | for (s32 g=7; g > 0; --g) | ||
213 | { | ||
214 | core::stringc tmp; | ||
215 | tmp = "../../media/portal"; | ||
216 | tmp += g; | ||
217 | tmp += ".bmp"; | ||
218 | video::ITexture* t = driver->getTexture( tmp.c_str() ); | ||
219 | textures.push_back(t); | ||
220 | } | ||
221 | |||
222 | // create texture animator | ||
223 | scene::ISceneNodeAnimator* glow = smgr->createTextureAnimator(textures, 150); | ||
224 | |||
225 | // add the animator | ||
226 | n->addAnimator(glow); | ||
227 | |||
228 | // drop the animator because it was created with a create() function | ||
229 | glow->drop(); | ||
230 | } | ||
231 | |||
232 | /* | ||
233 | As our last special effect, we want a dynamic shadow be casted from an | ||
234 | animated character. For this we load a DirectX .x model and place it | ||
235 | into our world. For creating the shadow, we simply need to call | ||
236 | addShadowVolumeSceneNode(). The color of shadows is only adjustable | ||
237 | globally for all shadows, by calling ISceneManager::setShadowColor(). | ||
238 | Voila, here is our dynamic shadow. | ||
239 | |||
240 | Because the character is a little bit too small for this scene, we make | ||
241 | it bigger using setScale(). And because the character is lighted by a | ||
242 | dynamic light, we need to normalize the normals to make the lighting on | ||
243 | it correct. This is always necessary if the scale of a dynamic lighted | ||
244 | model is not (1,1,1). Otherwise it would get too dark or too bright | ||
245 | because the normals will be scaled too. | ||
246 | */ | ||
247 | |||
248 | // add animated character | ||
249 | |||
250 | mesh = smgr->getMesh("../../media/dwarf.x"); | ||
251 | scene::IAnimatedMeshSceneNode* anode = 0; | ||
252 | |||
253 | anode = smgr->addAnimatedMeshSceneNode(mesh); | ||
254 | anode->setPosition(core::vector3df(-50,20,-60)); | ||
255 | anode->setAnimationSpeed(15); | ||
256 | |||
257 | // add shadow | ||
258 | anode->addShadowVolumeSceneNode(); | ||
259 | smgr->setShadowColor(video::SColor(150,0,0,0)); | ||
260 | |||
261 | // make the model a little bit bigger and normalize its normals | ||
262 | // because of the scaling, for correct lighting | ||
263 | anode->setScale(core::vector3df(2,2,2)); | ||
264 | anode->setMaterialFlag(video::EMF_NORMALIZE_NORMALS, true); | ||
265 | |||
266 | /* | ||
267 | Finally we simply have to draw everything, that's all. | ||
268 | */ | ||
269 | |||
270 | scene::ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS(); | ||
271 | camera->setPosition(core::vector3df(-50,50,-150)); | ||
272 | camera->setFarValue(10000.0f); // this increase a shadow visible range. | ||
273 | |||
274 | // disable mouse cursor | ||
275 | device->getCursorControl()->setVisible(false); | ||
276 | |||
277 | s32 lastFPS = -1; | ||
278 | |||
279 | while(device->run()) | ||
280 | if (device->isWindowActive()) | ||
281 | { | ||
282 | driver->beginScene(true, true, 0); | ||
283 | |||
284 | smgr->drawAll(); | ||
285 | |||
286 | driver->endScene(); | ||
287 | |||
288 | const s32 fps = driver->getFPS(); | ||
289 | |||
290 | if (lastFPS != fps) | ||
291 | { | ||
292 | core::stringw str = L"Irrlicht Engine - SpecialFX example ["; | ||
293 | str += driver->getName(); | ||
294 | str += "] FPS:"; | ||
295 | str += fps; | ||
296 | |||
297 | device->setWindowCaption(str.c_str()); | ||
298 | lastFPS = fps; | ||
299 | } | ||
300 | } | ||
301 | |||
302 | device->drop(); | ||
303 | |||
304 | return 0; | ||
305 | } | ||
306 | |||
307 | /* | ||
308 | **/ | ||