aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/others/irrlicht-1.8.1/examples/07.Collision/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/others/irrlicht-1.8.1/examples/07.Collision/main.cpp')
-rw-r--r--src/others/irrlicht-1.8.1/examples/07.Collision/main.cpp330
1 files changed, 330 insertions, 0 deletions
diff --git a/src/others/irrlicht-1.8.1/examples/07.Collision/main.cpp b/src/others/irrlicht-1.8.1/examples/07.Collision/main.cpp
new file mode 100644
index 0000000..8387c49
--- /dev/null
+++ b/src/others/irrlicht-1.8.1/examples/07.Collision/main.cpp
@@ -0,0 +1,330 @@
1/** Example 007 Collision
2
3We will describe 2 methods: Automatic collision detection for moving through
43d worlds with stair climbing and sliding, and manual scene node and triangle
5picking using a ray. In this case, we will use a ray coming out from the
6camera, but you can use any ray.
7
8To start, we take the program from tutorial 2, which loads and displays a
9quake 3 level. We will use the level to walk in it and to pick triangles from.
10In addition we'll place 3 animated models into it for triangle picking. The
11following code starts up the engine and loads the level, as per tutorial 2.
12*/
13#include <irrlicht.h>
14#include "driverChoice.h"
15
16using namespace irr;
17
18#ifdef _MSC_VER
19#pragma comment(lib, "Irrlicht.lib")
20#endif
21
22enum
23{
24 // I use this ISceneNode ID to indicate a scene node that is
25 // not pickable by getSceneNodeAndCollisionPointFromRay()
26 ID_IsNotPickable = 0,
27
28 // I use this flag in ISceneNode IDs to indicate that the
29 // scene node can be picked by ray selection.
30 IDFlag_IsPickable = 1 << 0,
31
32 // I use this flag in ISceneNode IDs to indicate that the
33 // scene node can be highlighted. In this example, the
34 // homonids can be highlighted, but the level mesh can't.
35 IDFlag_IsHighlightable = 1 << 1
36};
37
38int main()
39{
40 // ask user for driver
41 video::E_DRIVER_TYPE driverType=driverChoiceConsole();
42 if (driverType==video::EDT_COUNT)
43 return 1;
44
45 // create device
46
47 IrrlichtDevice *device =
48 createDevice(driverType, core::dimension2d<u32>(640, 480), 16, false);
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 device->getFileSystem()->addFileArchive("../../media/map-20kdm2.pk3");
57
58 scene::IAnimatedMesh* q3levelmesh = smgr->getMesh("20kdm2.bsp");
59 scene::IMeshSceneNode* q3node = 0;
60
61 // The Quake mesh is pickable, but doesn't get highlighted.
62 if (q3levelmesh)
63 q3node = smgr->addOctreeSceneNode(q3levelmesh->getMesh(0), 0, IDFlag_IsPickable);
64
65 /*
66 So far so good, we've loaded the quake 3 level like in tutorial 2. Now,
67 here comes something different: We create a triangle selector. A
68 triangle selector is a class which can fetch the triangles from scene
69 nodes for doing different things with them, for example collision
70 detection. There are different triangle selectors, and all can be
71 created with the ISceneManager. In this example, we create an
72 OctreeTriangleSelector, which optimizes the triangle output a little
73 bit by reducing it like an octree. This is very useful for huge meshes
74 like quake 3 levels. After we created the triangle selector, we attach
75 it to the q3node. This is not necessary, but in this way, we do not
76 need to care for the selector, for example dropping it after we do not
77 need it anymore.
78 */
79
80 scene::ITriangleSelector* selector = 0;
81
82 if (q3node)
83 {
84 q3node->setPosition(core::vector3df(-1350,-130,-1400));
85
86 selector = smgr->createOctreeTriangleSelector(
87 q3node->getMesh(), q3node, 128);
88 q3node->setTriangleSelector(selector);
89 // We're not done with this selector yet, so don't drop it.
90 }
91
92
93 /*
94 We add a first person shooter camera to the scene so that we can see and
95 move in the quake 3 level like in tutorial 2. But this, time, we add a
96 special animator to the camera: A Collision Response animator. This
97 animator modifies the scene node to which it is attached to in order to
98 prevent it moving through walls, and to add gravity to it. The
99 only thing we have to tell the animator is how the world looks like,
100 how big the scene node is, how much gravity to apply and so on. After the
101 collision response animator is attached to the camera, we do not have to do
102 anything more for collision detection, anything is done automatically.
103 The rest of the collision detection code below is for picking. And please
104 note another cool feature: The collision response animator can be
105 attached also to all other scene nodes, not only to cameras. And it can
106 be mixed with other scene node animators. In this way, collision
107 detection and response in the Irrlicht engine is really easy.
108
109 Now we'll take a closer look on the parameters of
110 createCollisionResponseAnimator(). The first parameter is the
111 TriangleSelector, which specifies how the world, against collision
112 detection is done looks like. The second parameter is the scene node,
113 which is the object, which is affected by collision detection, in our
114 case it is the camera. The third defines how big the object is, it is
115 the radius of an ellipsoid. Try it out and change the radius to smaller
116 values, the camera will be able to move closer to walls after this. The
117 next parameter is the direction and speed of gravity. We'll set it to
118 (0, -10, 0), which approximates to realistic gravity, assuming that our
119 units are metres. You could set it to (0,0,0) to disable gravity. And the
120 last value is just a translation: Without this, the ellipsoid with which
121 collision detection is done would be around the camera, and the camera would
122 be in the middle of the ellipsoid. But as human beings, we are used to have our
123 eyes on top of the body, with which we collide with our world, not in
124 the middle of it. So we place the scene node 50 units over the center
125 of the ellipsoid with this parameter. And that's it, collision
126 detection works now.
127 */
128
129 // Set a jump speed of 3 units per second, which gives a fairly realistic jump
130 // when used with the gravity of (0, -10, 0) in the collision response animator.
131 scene::ICameraSceneNode* camera =
132 smgr->addCameraSceneNodeFPS(0, 100.0f, .3f, ID_IsNotPickable, 0, 0, true, 3.f);
133 camera->setPosition(core::vector3df(50,50,-60));
134 camera->setTarget(core::vector3df(-70,30,-60));
135
136 if (selector)
137 {
138 scene::ISceneNodeAnimator* anim = smgr->createCollisionResponseAnimator(
139 selector, camera, core::vector3df(30,50,30),
140 core::vector3df(0,-10,0), core::vector3df(0,30,0));
141 selector->drop(); // As soon as we're done with the selector, drop it.
142 camera->addAnimator(anim);
143 anim->drop(); // And likewise, drop the animator when we're done referring to it.
144 }
145
146 // Now I create three animated characters which we can pick, a dynamic light for
147 // lighting them, and a billboard for drawing where we found an intersection.
148
149 // First, let's get rid of the mouse cursor. We'll use a billboard to show
150 // what we're looking at.
151 device->getCursorControl()->setVisible(false);
152
153 // Add the billboard.
154 scene::IBillboardSceneNode * bill = smgr->addBillboardSceneNode();
155 bill->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR );
156 bill->setMaterialTexture(0, driver->getTexture("../../media/particle.bmp"));
157 bill->setMaterialFlag(video::EMF_LIGHTING, false);
158 bill->setMaterialFlag(video::EMF_ZBUFFER, false);
159 bill->setSize(core::dimension2d<f32>(20.0f, 20.0f));
160 bill->setID(ID_IsNotPickable); // This ensures that we don't accidentally ray-pick it
161
162 /* Add 3 animated hominids, which we can pick using a ray-triangle intersection.
163 They all animate quite slowly, to make it easier to see that accurate triangle
164 selection is being performed. */
165 scene::IAnimatedMeshSceneNode* node = 0;
166
167 video::SMaterial material;
168
169 // Add an MD2 node, which uses vertex-based animation.
170 node = smgr->addAnimatedMeshSceneNode(smgr->getMesh("../../media/faerie.md2"),
171 0, IDFlag_IsPickable | IDFlag_IsHighlightable);
172 node->setPosition(core::vector3df(-90,-15,-140)); // Put its feet on the floor.
173 node->setScale(core::vector3df(1.6f)); // Make it appear realistically scaled
174 node->setMD2Animation(scene::EMAT_POINT);
175 node->setAnimationSpeed(20.f);
176 material.setTexture(0, driver->getTexture("../../media/faerie2.bmp"));
177 material.Lighting = true;
178 material.NormalizeNormals = true;
179 node->getMaterial(0) = material;
180
181 // Now create a triangle selector for it. The selector will know that it
182 // is associated with an animated node, and will update itself as necessary.
183 selector = smgr->createTriangleSelector(node);
184 node->setTriangleSelector(selector);
185 selector->drop(); // We're done with this selector, so drop it now.
186
187 // And this B3D file uses skinned skeletal animation.
188 node = smgr->addAnimatedMeshSceneNode(smgr->getMesh("../../media/ninja.b3d"),
189 0, IDFlag_IsPickable | IDFlag_IsHighlightable);
190 node->setScale(core::vector3df(10));
191 node->setPosition(core::vector3df(-75,-66,-80));
192 node->setRotation(core::vector3df(0,90,0));
193 node->setAnimationSpeed(8.f);
194 node->getMaterial(0).NormalizeNormals = true;
195 node->getMaterial(0).Lighting = true;
196 // Just do the same as we did above.
197 selector = smgr->createTriangleSelector(node);
198 node->setTriangleSelector(selector);
199 selector->drop();
200
201 // This X files uses skeletal animation, but without skinning.
202 node = smgr->addAnimatedMeshSceneNode(smgr->getMesh("../../media/dwarf.x"),
203 0, IDFlag_IsPickable | IDFlag_IsHighlightable);
204 node->setPosition(core::vector3df(-70,-66,-30)); // Put its feet on the floor.
205 node->setRotation(core::vector3df(0,-90,0)); // And turn it towards the camera.
206 node->setAnimationSpeed(20.f);
207 node->getMaterial(0).Lighting = true;
208 selector = smgr->createTriangleSelector(node);
209 node->setTriangleSelector(selector);
210 selector->drop();
211
212
213 // And this mdl file uses skinned skeletal animation.
214 node = smgr->addAnimatedMeshSceneNode(smgr->getMesh("../../media/yodan.mdl"),
215 0, IDFlag_IsPickable | IDFlag_IsHighlightable);
216 node->setPosition(core::vector3df(-90,-25,20));
217 node->setScale(core::vector3df(0.8f));
218 node->getMaterial(0).Lighting = true;
219 node->setAnimationSpeed(20.f);
220
221 // Just do the same as we did above.
222 selector = smgr->createTriangleSelector(node);
223 node->setTriangleSelector(selector);
224 selector->drop();
225
226 material.setTexture(0, 0);
227 material.Lighting = false;
228
229 // Add a light, so that the unselected nodes aren't completely dark.
230 scene::ILightSceneNode * light = smgr->addLightSceneNode(0, core::vector3df(-60,100,400),
231 video::SColorf(1.0f,1.0f,1.0f,1.0f), 600.0f);
232 light->setID(ID_IsNotPickable); // Make it an invalid target for selection.
233
234 // Remember which scene node is highlighted
235 scene::ISceneNode* highlightedSceneNode = 0;
236 scene::ISceneCollisionManager* collMan = smgr->getSceneCollisionManager();
237 int lastFPS = -1;
238
239 // draw the selection triangle only as wireframe
240 material.Wireframe=true;
241
242 while(device->run())
243 if (device->isWindowActive())
244 {
245 driver->beginScene(true, true, 0);
246 smgr->drawAll();
247
248 // Unlight any currently highlighted scene node
249 if (highlightedSceneNode)
250 {
251 highlightedSceneNode->setMaterialFlag(video::EMF_LIGHTING, true);
252 highlightedSceneNode = 0;
253 }
254
255 // All intersections in this example are done with a ray cast out from the camera to
256 // a distance of 1000. You can easily modify this to check (e.g.) a bullet
257 // trajectory or a sword's position, or create a ray from a mouse click position using
258 // ISceneCollisionManager::getRayFromScreenCoordinates()
259 core::line3d<f32> ray;
260 ray.start = camera->getPosition();
261 ray.end = ray.start + (camera->getTarget() - ray.start).normalize() * 1000.0f;
262
263 // Tracks the current intersection point with the level or a mesh
264 core::vector3df intersection;
265 // Used to show with triangle has been hit
266 core::triangle3df hitTriangle;
267
268 // This call is all you need to perform ray/triangle collision on every scene node
269 // that has a triangle selector, including the Quake level mesh. It finds the nearest
270 // collision point/triangle, and returns the scene node containing that point.
271 // Irrlicht provides other types of selection, including ray/triangle selector,
272 // ray/box and ellipse/triangle selector, plus associated helpers.
273 // See the methods of ISceneCollisionManager
274 scene::ISceneNode * selectedSceneNode =
275 collMan->getSceneNodeAndCollisionPointFromRay(
276 ray,
277 intersection, // This will be the position of the collision
278 hitTriangle, // This will be the triangle hit in the collision
279 IDFlag_IsPickable, // This ensures that only nodes that we have
280 // set up to be pickable are considered
281 0); // Check the entire scene (this is actually the implicit default)
282
283 // If the ray hit anything, move the billboard to the collision position
284 // and draw the triangle that was hit.
285 if(selectedSceneNode)
286 {
287 bill->setPosition(intersection);
288
289 // We need to reset the transform before doing our own rendering.
290 driver->setTransform(video::ETS_WORLD, core::matrix4());
291 driver->setMaterial(material);
292 driver->draw3DTriangle(hitTriangle, video::SColor(0,255,0,0));
293
294 // We can check the flags for the scene node that was hit to see if it should be
295 // highlighted. The animated nodes can be highlighted, but not the Quake level mesh
296 if((selectedSceneNode->getID() & IDFlag_IsHighlightable) == IDFlag_IsHighlightable)
297 {
298 highlightedSceneNode = selectedSceneNode;
299
300 // Highlighting in this case means turning lighting OFF for this node,
301 // which means that it will be drawn with full brightness.
302 highlightedSceneNode->setMaterialFlag(video::EMF_LIGHTING, false);
303 }
304 }
305
306 // We're all done drawing, so end the scene.
307 driver->endScene();
308
309 int fps = driver->getFPS();
310
311 if (lastFPS != fps)
312 {
313 core::stringw str = L"Collision detection example - Irrlicht Engine [";
314 str += driver->getName();
315 str += "] FPS:";
316 str += fps;
317
318 device->setWindowCaption(str.c_str());
319 lastFPS = fps;
320 }
321 }
322
323 device->drop();
324
325 return 0;
326}
327
328/*
329**/
330