diff options
Diffstat (limited to '')
-rw-r--r-- | libraries/irrlicht-1.8/examples/23.SMeshHandling/main.cpp | 852 |
1 files changed, 426 insertions, 426 deletions
diff --git a/libraries/irrlicht-1.8/examples/23.SMeshHandling/main.cpp b/libraries/irrlicht-1.8/examples/23.SMeshHandling/main.cpp index c3c2ccf..d36fb24 100644 --- a/libraries/irrlicht-1.8/examples/23.SMeshHandling/main.cpp +++ b/libraries/irrlicht-1.8/examples/23.SMeshHandling/main.cpp | |||
@@ -1,426 +1,426 @@ | |||
1 | /** Example 023 SMeshBufferHandling | 1 | /** Example 023 SMeshBufferHandling |
2 | 2 | ||
3 | A tutorial by geoff. | 3 | A tutorial by geoff. |
4 | 4 | ||
5 | In this tutorial we'll learn how to create custom meshes and deal with them | 5 | In this tutorial we'll learn how to create custom meshes and deal with them |
6 | with Irrlicht. We'll create an interesting heightmap with some lighting effects. | 6 | with Irrlicht. We'll create an interesting heightmap with some lighting effects. |
7 | With keys 1,2,3 you can choose a different mesh layout, which is put into the | 7 | With keys 1,2,3 you can choose a different mesh layout, which is put into the |
8 | mesh buffers as desired. All positions, normals, etc. are updated accordingly. | 8 | mesh buffers as desired. All positions, normals, etc. are updated accordingly. |
9 | 9 | ||
10 | Ok, let's start with the headers (I think there's nothing to say about it) | 10 | Ok, let's start with the headers (I think there's nothing to say about it) |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <irrlicht.h> | 13 | #include <irrlicht.h> |
14 | #include "driverChoice.h" | 14 | #include "driverChoice.h" |
15 | 15 | ||
16 | #ifdef _MSC_VER | 16 | #ifdef _MSC_VER |
17 | #pragma comment(lib, "Irrlicht.lib") | 17 | #pragma comment(lib, "Irrlicht.lib") |
18 | #endif | 18 | #endif |
19 | 19 | ||
20 | //Namespaces for the engine | 20 | //Namespaces for the engine |
21 | using namespace irr; | 21 | using namespace irr; |
22 | using namespace video; | 22 | using namespace video; |
23 | using namespace core; | 23 | using namespace core; |
24 | using namespace scene; | 24 | using namespace scene; |
25 | using namespace io; | 25 | using namespace io; |
26 | using namespace gui; | 26 | using namespace gui; |
27 | 27 | ||
28 | /* This is the type of the functions which work out the colour. */ | 28 | /* This is the type of the functions which work out the colour. */ |
29 | typedef SColor colour_func(f32 x, f32 y, f32 z); | 29 | typedef SColor colour_func(f32 x, f32 y, f32 z); |
30 | 30 | ||
31 | /* Here comes a set of functions which can be used for coloring the nodes while | 31 | /* Here comes a set of functions which can be used for coloring the nodes while |
32 | creating the mesh. */ | 32 | creating the mesh. */ |
33 | 33 | ||
34 | // Greyscale, based on the height. | 34 | // Greyscale, based on the height. |
35 | SColor grey(f32, f32, f32 z) | 35 | SColor grey(f32, f32, f32 z) |
36 | { | 36 | { |
37 | u32 n = (u32)(255.f * z); | 37 | u32 n = (u32)(255.f * z); |
38 | return SColor(255, n, n, n); | 38 | return SColor(255, n, n, n); |
39 | } | 39 | } |
40 | 40 | ||
41 | // Interpolation between blue and white, with red added in one | 41 | // Interpolation between blue and white, with red added in one |
42 | // direction and green in the other. | 42 | // direction and green in the other. |
43 | SColor yellow(f32 x, f32 y, f32) | 43 | SColor yellow(f32 x, f32 y, f32) |
44 | { | 44 | { |
45 | return SColor(255, 128 + (u32)(127.f * x), 128 + (u32)(127.f * y), 255); | 45 | return SColor(255, 128 + (u32)(127.f * x), 128 + (u32)(127.f * y), 255); |
46 | } | 46 | } |
47 | 47 | ||
48 | // Pure white. | 48 | // Pure white. |
49 | SColor white(f32, f32, f32) { return SColor(255, 255, 255, 255); } | 49 | SColor white(f32, f32, f32) { return SColor(255, 255, 255, 255); } |
50 | 50 | ||
51 | /* The type of the functions which generate the heightmap. x and y | 51 | /* The type of the functions which generate the heightmap. x and y |
52 | range between -0.5 and 0.5, and s is the scale of the heightmap. */ | 52 | range between -0.5 and 0.5, and s is the scale of the heightmap. */ |
53 | 53 | ||
54 | typedef f32 generate_func(s16 x, s16 y, f32 s); | 54 | typedef f32 generate_func(s16 x, s16 y, f32 s); |
55 | 55 | ||
56 | // An interesting sample function :-) | 56 | // An interesting sample function :-) |
57 | f32 eggbox(s16 x, s16 y, f32 s) | 57 | f32 eggbox(s16 x, s16 y, f32 s) |
58 | { | 58 | { |
59 | const f32 r = 4.f*sqrtf((f32)(x*x + y*y))/s; | 59 | const f32 r = 4.f*sqrtf((f32)(x*x + y*y))/s; |
60 | const f32 z = expf(-r * 2) * (cosf(0.2f * x) + cosf(0.2f * y)); | 60 | const f32 z = expf(-r * 2) * (cosf(0.2f * x) + cosf(0.2f * y)); |
61 | return 0.25f+0.25f*z; | 61 | return 0.25f+0.25f*z; |
62 | } | 62 | } |
63 | 63 | ||
64 | // A rather dumb sine function :-/ | 64 | // A rather dumb sine function :-/ |
65 | f32 moresine(s16 x, s16 y, f32 s) | 65 | f32 moresine(s16 x, s16 y, f32 s) |
66 | { | 66 | { |
67 | const f32 xx=0.3f*(f32)x/s; | 67 | const f32 xx=0.3f*(f32)x/s; |
68 | const f32 yy=12*y/s; | 68 | const f32 yy=12*y/s; |
69 | const f32 z = sinf(xx*xx+yy)*sinf(xx+yy*yy); | 69 | const f32 z = sinf(xx*xx+yy)*sinf(xx+yy*yy); |
70 | return 0.25f + 0.25f * z; | 70 | return 0.25f + 0.25f * z; |
71 | } | 71 | } |
72 | 72 | ||
73 | // A simple function | 73 | // A simple function |
74 | f32 justexp(s16 x, s16 y, f32 s) | 74 | f32 justexp(s16 x, s16 y, f32 s) |
75 | { | 75 | { |
76 | const f32 xx=6*x/s; | 76 | const f32 xx=6*x/s; |
77 | const f32 yy=6*y/s; | 77 | const f32 yy=6*y/s; |
78 | const f32 z = (xx*xx+yy*yy); | 78 | const f32 z = (xx*xx+yy*yy); |
79 | return 0.3f*z*cosf(xx*yy); | 79 | return 0.3f*z*cosf(xx*yy); |
80 | } | 80 | } |
81 | 81 | ||
82 | /* A simple class for representing heightmaps. Most of this should be obvious. */ | 82 | /* A simple class for representing heightmaps. Most of this should be obvious. */ |
83 | 83 | ||
84 | class HeightMap | 84 | class HeightMap |
85 | { | 85 | { |
86 | private: | 86 | private: |
87 | const u16 Width; | 87 | const u16 Width; |
88 | const u16 Height; | 88 | const u16 Height; |
89 | f32 s; | 89 | f32 s; |
90 | core::array<f32> data; | 90 | core::array<f32> data; |
91 | public: | 91 | public: |
92 | HeightMap(u16 _w, u16 _h) : Width(_w), Height(_h), s(0.f), data(0) | 92 | HeightMap(u16 _w, u16 _h) : Width(_w), Height(_h), s(0.f), data(0) |
93 | { | 93 | { |
94 | s = sqrtf((f32)(Width * Width + Height * Height)); | 94 | s = sqrtf((f32)(Width * Width + Height * Height)); |
95 | data.set_used(Width * Height); | 95 | data.set_used(Width * Height); |
96 | } | 96 | } |
97 | 97 | ||
98 | // Fill the heightmap with values generated from f. | 98 | // Fill the heightmap with values generated from f. |
99 | void generate(generate_func f) | 99 | void generate(generate_func f) |
100 | { | 100 | { |
101 | u32 i=0; | 101 | u32 i=0; |
102 | for(u16 y = 0; y < Height; ++y) | 102 | for(u16 y = 0; y < Height; ++y) |
103 | for(u16 x = 0; x < Width; ++x) | 103 | for(u16 x = 0; x < Width; ++x) |
104 | set(i++, calc(f, x, y)); | 104 | set(i++, calc(f, x, y)); |
105 | } | 105 | } |
106 | 106 | ||
107 | u16 height() const { return Height; } | 107 | u16 height() const { return Height; } |
108 | u16 width() const { return Width; } | 108 | u16 width() const { return Width; } |
109 | 109 | ||
110 | f32 calc(generate_func f, u16 x, u16 y) const | 110 | f32 calc(generate_func f, u16 x, u16 y) const |
111 | { | 111 | { |
112 | const f32 xx = (f32)x - Width*0.5f; | 112 | const f32 xx = (f32)x - Width*0.5f; |
113 | const f32 yy = (f32)y - Height*0.5f; | 113 | const f32 yy = (f32)y - Height*0.5f; |
114 | return f((u16)xx, (u16)yy, s); | 114 | return f((u16)xx, (u16)yy, s); |
115 | } | 115 | } |
116 | 116 | ||
117 | // The height at (x, y) is at position y * Width + x. | 117 | // The height at (x, y) is at position y * Width + x. |
118 | 118 | ||
119 | void set(u16 x, u16 y, f32 z) { data[y * Width + x] = z; } | 119 | void set(u16 x, u16 y, f32 z) { data[y * Width + x] = z; } |
120 | void set(u32 i, f32 z) { data[i] = z; } | 120 | void set(u32 i, f32 z) { data[i] = z; } |
121 | f32 get(u16 x, u16 y) const { return data[y * Width + x]; } | 121 | f32 get(u16 x, u16 y) const { return data[y * Width + x]; } |
122 | 122 | ||
123 | /* The only difficult part. This considers the normal at (x, y) to | 123 | /* The only difficult part. This considers the normal at (x, y) to |
124 | be the cross product of the vectors between the adjacent points | 124 | be the cross product of the vectors between the adjacent points |
125 | in the horizontal and vertical directions. | 125 | in the horizontal and vertical directions. |
126 | 126 | ||
127 | s is a scaling factor, which is necessary if the height units are | 127 | s is a scaling factor, which is necessary if the height units are |
128 | different from the coordinate units; for example, if your map has | 128 | different from the coordinate units; for example, if your map has |
129 | heights in metres and the coordinates are in units of a | 129 | heights in metres and the coordinates are in units of a |
130 | kilometer. */ | 130 | kilometer. */ |
131 | 131 | ||
132 | vector3df getnormal(u16 x, u16 y, f32 s) const | 132 | vector3df getnormal(u16 x, u16 y, f32 s) const |
133 | { | 133 | { |
134 | const f32 zc = get(x, y); | 134 | const f32 zc = get(x, y); |
135 | f32 zl, zr, zu, zd; | 135 | f32 zl, zr, zu, zd; |
136 | 136 | ||
137 | if (x == 0) | 137 | if (x == 0) |
138 | { | 138 | { |
139 | zr = get(x + 1, y); | 139 | zr = get(x + 1, y); |
140 | zl = zc + zc - zr; | 140 | zl = zc + zc - zr; |
141 | } | 141 | } |
142 | else if (x == Width - 1) | 142 | else if (x == Width - 1) |
143 | { | 143 | { |
144 | zl = get(x - 1, y); | 144 | zl = get(x - 1, y); |
145 | zr = zc + zc - zl; | 145 | zr = zc + zc - zl; |
146 | } | 146 | } |
147 | else | 147 | else |
148 | { | 148 | { |
149 | zr = get(x + 1, y); | 149 | zr = get(x + 1, y); |
150 | zl = get(x - 1, y); | 150 | zl = get(x - 1, y); |
151 | } | 151 | } |
152 | 152 | ||
153 | if (y == 0) | 153 | if (y == 0) |
154 | { | 154 | { |
155 | zd = get(x, y + 1); | 155 | zd = get(x, y + 1); |
156 | zu = zc + zc - zd; | 156 | zu = zc + zc - zd; |
157 | } | 157 | } |
158 | else if (y == Height - 1) | 158 | else if (y == Height - 1) |
159 | { | 159 | { |
160 | zu = get(x, y - 1); | 160 | zu = get(x, y - 1); |
161 | zd = zc + zc - zu; | 161 | zd = zc + zc - zu; |
162 | } | 162 | } |
163 | else | 163 | else |
164 | { | 164 | { |
165 | zd = get(x, y + 1); | 165 | zd = get(x, y + 1); |
166 | zu = get(x, y - 1); | 166 | zu = get(x, y - 1); |
167 | } | 167 | } |
168 | 168 | ||
169 | return vector3df(s * 2 * (zl - zr), 4, s * 2 * (zd - zu)).normalize(); | 169 | return vector3df(s * 2 * (zl - zr), 4, s * 2 * (zd - zu)).normalize(); |
170 | } | 170 | } |
171 | }; | 171 | }; |
172 | 172 | ||
173 | /* A class which generates a mesh from a heightmap. */ | 173 | /* A class which generates a mesh from a heightmap. */ |
174 | class TMesh | 174 | class TMesh |
175 | { | 175 | { |
176 | private: | 176 | private: |
177 | u16 Width; | 177 | u16 Width; |
178 | u16 Height; | 178 | u16 Height; |
179 | f32 Scale; | 179 | f32 Scale; |
180 | public: | 180 | public: |
181 | SMesh* Mesh; | 181 | SMesh* Mesh; |
182 | 182 | ||
183 | TMesh() : Mesh(0), Width(0), Height(0), Scale(1.f) | 183 | TMesh() : Mesh(0), Width(0), Height(0), Scale(1.f) |
184 | { | 184 | { |
185 | Mesh = new SMesh(); | 185 | Mesh = new SMesh(); |
186 | } | 186 | } |
187 | 187 | ||
188 | ~TMesh() | 188 | ~TMesh() |
189 | { | 189 | { |
190 | Mesh->drop(); | 190 | Mesh->drop(); |
191 | } | 191 | } |
192 | 192 | ||
193 | // Unless the heightmap is small, it won't all fit into a single | 193 | // Unless the heightmap is small, it won't all fit into a single |
194 | // SMeshBuffer. This function chops it into pieces and generates a | 194 | // SMeshBuffer. This function chops it into pieces and generates a |
195 | // buffer from each one. | 195 | // buffer from each one. |
196 | 196 | ||
197 | void init(const HeightMap &hm, f32 scale, colour_func cf, IVideoDriver *driver) | 197 | void init(const HeightMap &hm, f32 scale, colour_func cf, IVideoDriver *driver) |
198 | { | 198 | { |
199 | Scale = scale; | 199 | Scale = scale; |
200 | 200 | ||
201 | const u32 mp = driver -> getMaximalPrimitiveCount(); | 201 | const u32 mp = driver -> getMaximalPrimitiveCount(); |
202 | Width = hm.width(); | 202 | Width = hm.width(); |
203 | Height = hm.height(); | 203 | Height = hm.height(); |
204 | 204 | ||
205 | const u32 sw = mp / (6 * Height); // the width of each piece | 205 | const u32 sw = mp / (6 * Height); // the width of each piece |
206 | 206 | ||
207 | u32 i=0; | 207 | u32 i=0; |
208 | for(u32 y0 = 0; y0 < Height; y0 += sw) | 208 | for(u32 y0 = 0; y0 < Height; y0 += sw) |
209 | { | 209 | { |
210 | u16 y1 = y0 + sw; | 210 | u16 y1 = y0 + sw; |
211 | if (y1 >= Height) | 211 | if (y1 >= Height) |
212 | y1 = Height - 1; // the last one might be narrower | 212 | y1 = Height - 1; // the last one might be narrower |
213 | addstrip(hm, cf, y0, y1, i); | 213 | addstrip(hm, cf, y0, y1, i); |
214 | ++i; | 214 | ++i; |
215 | } | 215 | } |
216 | if (i<Mesh->getMeshBufferCount()) | 216 | if (i<Mesh->getMeshBufferCount()) |
217 | { | 217 | { |
218 | // clear the rest | 218 | // clear the rest |
219 | for (u32 j=i; j<Mesh->getMeshBufferCount(); ++j) | 219 | for (u32 j=i; j<Mesh->getMeshBufferCount(); ++j) |
220 | { | 220 | { |
221 | Mesh->getMeshBuffer(j)->drop(); | 221 | Mesh->getMeshBuffer(j)->drop(); |
222 | } | 222 | } |
223 | Mesh->MeshBuffers.erase(i,Mesh->getMeshBufferCount()-i); | 223 | Mesh->MeshBuffers.erase(i,Mesh->getMeshBufferCount()-i); |
224 | } | 224 | } |
225 | // set dirty flag to make sure that hardware copies of this | 225 | // set dirty flag to make sure that hardware copies of this |
226 | // buffer are also updated, see IMesh::setHardwareMappingHint | 226 | // buffer are also updated, see IMesh::setHardwareMappingHint |
227 | Mesh->setDirty(); | 227 | Mesh->setDirty(); |
228 | Mesh->recalculateBoundingBox(); | 228 | Mesh->recalculateBoundingBox(); |
229 | } | 229 | } |
230 | 230 | ||
231 | // Generate a SMeshBuffer which represents all the vertices and | 231 | // Generate a SMeshBuffer which represents all the vertices and |
232 | // indices for values of y between y0 and y1, and add it to the | 232 | // indices for values of y between y0 and y1, and add it to the |
233 | // mesh. | 233 | // mesh. |
234 | 234 | ||
235 | void addstrip(const HeightMap &hm, colour_func cf, u16 y0, u16 y1, u32 bufNum) | 235 | void addstrip(const HeightMap &hm, colour_func cf, u16 y0, u16 y1, u32 bufNum) |
236 | { | 236 | { |
237 | SMeshBuffer *buf = 0; | 237 | SMeshBuffer *buf = 0; |
238 | if (bufNum<Mesh->getMeshBufferCount()) | 238 | if (bufNum<Mesh->getMeshBufferCount()) |
239 | { | 239 | { |
240 | buf = (SMeshBuffer*)Mesh->getMeshBuffer(bufNum); | 240 | buf = (SMeshBuffer*)Mesh->getMeshBuffer(bufNum); |
241 | } | 241 | } |
242 | else | 242 | else |
243 | { | 243 | { |
244 | // create new buffer | 244 | // create new buffer |
245 | buf = new SMeshBuffer(); | 245 | buf = new SMeshBuffer(); |
246 | Mesh->addMeshBuffer(buf); | 246 | Mesh->addMeshBuffer(buf); |
247 | // to simplify things we drop here but continue using buf | 247 | // to simplify things we drop here but continue using buf |
248 | buf->drop(); | 248 | buf->drop(); |
249 | } | 249 | } |
250 | buf->Vertices.set_used((1 + y1 - y0) * Width); | 250 | buf->Vertices.set_used((1 + y1 - y0) * Width); |
251 | 251 | ||
252 | u32 i=0; | 252 | u32 i=0; |
253 | for (u16 y = y0; y <= y1; ++y) | 253 | for (u16 y = y0; y <= y1; ++y) |
254 | { | 254 | { |
255 | for (u16 x = 0; x < Width; ++x) | 255 | for (u16 x = 0; x < Width; ++x) |
256 | { | 256 | { |
257 | const f32 z = hm.get(x, y); | 257 | const f32 z = hm.get(x, y); |
258 | const f32 xx = (f32)x/(f32)Width; | 258 | const f32 xx = (f32)x/(f32)Width; |
259 | const f32 yy = (f32)y/(f32)Height; | 259 | const f32 yy = (f32)y/(f32)Height; |
260 | 260 | ||
261 | S3DVertex& v = buf->Vertices[i++]; | 261 | S3DVertex& v = buf->Vertices[i++]; |
262 | v.Pos.set(x, Scale * z, y); | 262 | v.Pos.set(x, Scale * z, y); |
263 | v.Normal.set(hm.getnormal(x, y, Scale)); | 263 | v.Normal.set(hm.getnormal(x, y, Scale)); |
264 | v.Color=cf(xx, yy, z); | 264 | v.Color=cf(xx, yy, z); |
265 | v.TCoords.set(xx, yy); | 265 | v.TCoords.set(xx, yy); |
266 | } | 266 | } |
267 | } | 267 | } |
268 | 268 | ||
269 | buf->Indices.set_used(6 * (Width - 1) * (y1 - y0)); | 269 | buf->Indices.set_used(6 * (Width - 1) * (y1 - y0)); |
270 | i=0; | 270 | i=0; |
271 | for(u16 y = y0; y < y1; ++y) | 271 | for(u16 y = y0; y < y1; ++y) |
272 | { | 272 | { |
273 | for(u16 x = 0; x < Width - 1; ++x) | 273 | for(u16 x = 0; x < Width - 1; ++x) |
274 | { | 274 | { |
275 | const u16 n = (y-y0) * Width + x; | 275 | const u16 n = (y-y0) * Width + x; |
276 | buf->Indices[i]=n; | 276 | buf->Indices[i]=n; |
277 | buf->Indices[++i]=n + Width; | 277 | buf->Indices[++i]=n + Width; |
278 | buf->Indices[++i]=n + Width + 1; | 278 | buf->Indices[++i]=n + Width + 1; |
279 | buf->Indices[++i]=n + Width + 1; | 279 | buf->Indices[++i]=n + Width + 1; |
280 | buf->Indices[++i]=n + 1; | 280 | buf->Indices[++i]=n + 1; |
281 | buf->Indices[++i]=n; | 281 | buf->Indices[++i]=n; |
282 | ++i; | 282 | ++i; |
283 | } | 283 | } |
284 | } | 284 | } |
285 | 285 | ||
286 | buf->recalculateBoundingBox(); | 286 | buf->recalculateBoundingBox(); |
287 | } | 287 | } |
288 | }; | 288 | }; |
289 | 289 | ||
290 | /* | 290 | /* |
291 | Our event receiver implementation, taken from tutorial 4. | 291 | Our event receiver implementation, taken from tutorial 4. |
292 | */ | 292 | */ |
293 | class MyEventReceiver : public IEventReceiver | 293 | class MyEventReceiver : public IEventReceiver |
294 | { | 294 | { |
295 | public: | 295 | public: |
296 | // This is the one method that we have to implement | 296 | // This is the one method that we have to implement |
297 | virtual bool OnEvent(const SEvent& event) | 297 | virtual bool OnEvent(const SEvent& event) |
298 | { | 298 | { |
299 | // Remember whether each key is down or up | 299 | // Remember whether each key is down or up |
300 | if (event.EventType == irr::EET_KEY_INPUT_EVENT) | 300 | if (event.EventType == irr::EET_KEY_INPUT_EVENT) |
301 | KeyIsDown[event.KeyInput.Key] = event.KeyInput.PressedDown; | 301 | KeyIsDown[event.KeyInput.Key] = event.KeyInput.PressedDown; |
302 | 302 | ||
303 | return false; | 303 | return false; |
304 | } | 304 | } |
305 | 305 | ||
306 | // This is used to check whether a key is being held down | 306 | // This is used to check whether a key is being held down |
307 | virtual bool IsKeyDown(EKEY_CODE keyCode) const | 307 | virtual bool IsKeyDown(EKEY_CODE keyCode) const |
308 | { | 308 | { |
309 | return KeyIsDown[keyCode]; | 309 | return KeyIsDown[keyCode]; |
310 | } | 310 | } |
311 | 311 | ||
312 | MyEventReceiver() | 312 | MyEventReceiver() |
313 | { | 313 | { |
314 | for (u32 i=0; i<KEY_KEY_CODES_COUNT; ++i) | 314 | for (u32 i=0; i<KEY_KEY_CODES_COUNT; ++i) |
315 | KeyIsDown[i] = false; | 315 | KeyIsDown[i] = false; |
316 | } | 316 | } |
317 | 317 | ||
318 | private: | 318 | private: |
319 | // We use this array to store the current state of each key | 319 | // We use this array to store the current state of each key |
320 | bool KeyIsDown[KEY_KEY_CODES_COUNT]; | 320 | bool KeyIsDown[KEY_KEY_CODES_COUNT]; |
321 | }; | 321 | }; |
322 | 322 | ||
323 | /* | 323 | /* |
324 | Much of this is code taken from some of the examples. We merely set | 324 | Much of this is code taken from some of the examples. We merely set |
325 | up a mesh from a heightmap, light it with a moving light, and allow | 325 | up a mesh from a heightmap, light it with a moving light, and allow |
326 | the user to navigate around it. | 326 | the user to navigate around it. |
327 | */ | 327 | */ |
328 | 328 | ||
329 | int main(int argc, char* argv[]) | 329 | int main(int argc, char* argv[]) |
330 | { | 330 | { |
331 | // ask user for driver | 331 | // ask user for driver |
332 | video::E_DRIVER_TYPE driverType=driverChoiceConsole(); | 332 | video::E_DRIVER_TYPE driverType=driverChoiceConsole(); |
333 | if (driverType==video::EDT_COUNT) | 333 | if (driverType==video::EDT_COUNT) |
334 | return 1; | 334 | return 1; |
335 | 335 | ||
336 | MyEventReceiver receiver; | 336 | MyEventReceiver receiver; |
337 | IrrlichtDevice* device = createDevice(driverType, | 337 | IrrlichtDevice* device = createDevice(driverType, |
338 | core::dimension2du(800, 600), 32, false, false, false, | 338 | core::dimension2du(800, 600), 32, false, false, false, |
339 | &receiver); | 339 | &receiver); |
340 | 340 | ||
341 | if(device == 0) | 341 | if(device == 0) |
342 | return 1; | 342 | return 1; |
343 | 343 | ||
344 | IVideoDriver *driver = device->getVideoDriver(); | 344 | IVideoDriver *driver = device->getVideoDriver(); |
345 | ISceneManager *smgr = device->getSceneManager(); | 345 | ISceneManager *smgr = device->getSceneManager(); |
346 | device->setWindowCaption(L"Irrlicht Example for SMesh usage."); | 346 | device->setWindowCaption(L"Irrlicht Example for SMesh usage."); |
347 | 347 | ||
348 | /* | 348 | /* |
349 | Create the custom mesh and initialize with a heightmap | 349 | Create the custom mesh and initialize with a heightmap |
350 | */ | 350 | */ |
351 | TMesh mesh; | 351 | TMesh mesh; |
352 | HeightMap hm = HeightMap(255, 255); | 352 | HeightMap hm = HeightMap(255, 255); |
353 | hm.generate(eggbox); | 353 | hm.generate(eggbox); |
354 | mesh.init(hm, 50.f, grey, driver); | 354 | mesh.init(hm, 50.f, grey, driver); |
355 | 355 | ||
356 | // Add the mesh to the scene graph | 356 | // Add the mesh to the scene graph |
357 | IMeshSceneNode* meshnode = smgr -> addMeshSceneNode(mesh.Mesh); | 357 | IMeshSceneNode* meshnode = smgr -> addMeshSceneNode(mesh.Mesh); |
358 | meshnode->setMaterialFlag(video::EMF_BACK_FACE_CULLING, false); | 358 | meshnode->setMaterialFlag(video::EMF_BACK_FACE_CULLING, false); |
359 | 359 | ||
360 | // light is just for nice effects | 360 | // light is just for nice effects |
361 | ILightSceneNode *node = smgr->addLightSceneNode(0, vector3df(0,100,0), | 361 | ILightSceneNode *node = smgr->addLightSceneNode(0, vector3df(0,100,0), |
362 | SColorf(1.0f, 0.6f, 0.7f, 1.0f), 500.0f); | 362 | SColorf(1.0f, 0.6f, 0.7f, 1.0f), 500.0f); |
363 | if (node) | 363 | if (node) |
364 | { | 364 | { |
365 | node->getLightData().Attenuation.set(0.f, 1.f/500.f, 0.f); | 365 | node->getLightData().Attenuation.set(0.f, 1.f/500.f, 0.f); |
366 | ISceneNodeAnimator* anim = smgr->createFlyCircleAnimator(vector3df(0,150,0),250.0f); | 366 | ISceneNodeAnimator* anim = smgr->createFlyCircleAnimator(vector3df(0,150,0),250.0f); |
367 | if (anim) | 367 | if (anim) |
368 | { | 368 | { |
369 | node->addAnimator(anim); | 369 | node->addAnimator(anim); |
370 | anim->drop(); | 370 | anim->drop(); |
371 | } | 371 | } |
372 | } | 372 | } |
373 | 373 | ||
374 | ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS(); | 374 | ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS(); |
375 | if (camera) | 375 | if (camera) |
376 | { | 376 | { |
377 | camera->setPosition(vector3df(-20.f, 150.f, -20.f)); | 377 | camera->setPosition(vector3df(-20.f, 150.f, -20.f)); |
378 | camera->setTarget(vector3df(200.f, -80.f, 150.f)); | 378 | camera->setTarget(vector3df(200.f, -80.f, 150.f)); |
379 | camera->setFarValue(20000.0f); | 379 | camera->setFarValue(20000.0f); |
380 | } | 380 | } |
381 | 381 | ||
382 | /* | 382 | /* |
383 | Just a usual render loop with event handling. The custom mesh is | 383 | Just a usual render loop with event handling. The custom mesh is |
384 | a usual part of the scene graph which gets rendered by drawAll. | 384 | a usual part of the scene graph which gets rendered by drawAll. |
385 | */ | 385 | */ |
386 | while(device->run()) | 386 | while(device->run()) |
387 | { | 387 | { |
388 | if(!device->isWindowActive()) | 388 | if(!device->isWindowActive()) |
389 | { | 389 | { |
390 | device->sleep(100); | 390 | device->sleep(100); |
391 | continue; | 391 | continue; |
392 | } | 392 | } |
393 | 393 | ||
394 | if(receiver.IsKeyDown(irr::KEY_KEY_W)) | 394 | if(receiver.IsKeyDown(irr::KEY_KEY_W)) |
395 | { | 395 | { |
396 | meshnode->setMaterialFlag(video::EMF_WIREFRAME, !meshnode->getMaterial(0).Wireframe); | 396 | meshnode->setMaterialFlag(video::EMF_WIREFRAME, !meshnode->getMaterial(0).Wireframe); |
397 | } | 397 | } |
398 | else if(receiver.IsKeyDown(irr::KEY_KEY_1)) | 398 | else if(receiver.IsKeyDown(irr::KEY_KEY_1)) |
399 | { | 399 | { |
400 | hm.generate(eggbox); | 400 | hm.generate(eggbox); |
401 | mesh.init(hm, 50.f, grey, driver); | 401 | mesh.init(hm, 50.f, grey, driver); |
402 | } | 402 | } |
403 | else if(receiver.IsKeyDown(irr::KEY_KEY_2)) | 403 | else if(receiver.IsKeyDown(irr::KEY_KEY_2)) |
404 | { | 404 | { |
405 | hm.generate(moresine); | 405 | hm.generate(moresine); |
406 | mesh.init(hm, 50.f, yellow, driver); | 406 | mesh.init(hm, 50.f, yellow, driver); |
407 | } | 407 | } |
408 | else if(receiver.IsKeyDown(irr::KEY_KEY_3)) | 408 | else if(receiver.IsKeyDown(irr::KEY_KEY_3)) |
409 | { | 409 | { |
410 | hm.generate(justexp); | 410 | hm.generate(justexp); |
411 | mesh.init(hm, 50.f, yellow, driver); | 411 | mesh.init(hm, 50.f, yellow, driver); |
412 | } | 412 | } |
413 | 413 | ||
414 | driver->beginScene(true, true, SColor(0xff000000)); | 414 | driver->beginScene(true, true, SColor(0xff000000)); |
415 | smgr->drawAll(); | 415 | smgr->drawAll(); |
416 | driver->endScene(); | 416 | driver->endScene(); |
417 | } | 417 | } |
418 | 418 | ||
419 | device->drop(); | 419 | device->drop(); |
420 | 420 | ||
421 | return 0; | 421 | return 0; |
422 | } | 422 | } |
423 | 423 | ||
424 | /* | 424 | /* |
425 | That's it! Just compile and play around with the program. | 425 | That's it! Just compile and play around with the program. |
426 | **/ | 426 | **/ |