aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/irrlicht-1.8.1/source/Irrlicht/CGeometryCreator.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--libraries/irrlicht-1.8.1/source/Irrlicht/CGeometryCreator.cpp892
1 files changed, 892 insertions, 0 deletions
diff --git a/libraries/irrlicht-1.8.1/source/Irrlicht/CGeometryCreator.cpp b/libraries/irrlicht-1.8.1/source/Irrlicht/CGeometryCreator.cpp
new file mode 100644
index 0000000..c592833
--- /dev/null
+++ b/libraries/irrlicht-1.8.1/source/Irrlicht/CGeometryCreator.cpp
@@ -0,0 +1,892 @@
1// Copyright (C) 2002-2012 Nikolaus Gebhardt
2// This file is part of the "Irrlicht Engine".
3// For conditions of distribution and use, see copyright notice in irrlicht.h
4
5#include "CGeometryCreator.h"
6#include "SAnimatedMesh.h"
7#include "SMeshBuffer.h"
8#include "SMesh.h"
9#include "IMesh.h"
10#include "IVideoDriver.h"
11#include "os.h"
12
13namespace irr
14{
15namespace scene
16{
17
18IMesh* CGeometryCreator::createCubeMesh(const core::vector3df& size) const
19{
20 SMeshBuffer* buffer = new SMeshBuffer();
21
22 // Create indices
23 const u16 u[36] = { 0,2,1, 0,3,2, 1,5,4, 1,2,5, 4,6,7, 4,5,6,
24 7,3,0, 7,6,3, 9,5,2, 9,8,5, 0,11,10, 0,10,7};
25
26 buffer->Indices.set_used(36);
27
28 for (u32 i=0; i<36; ++i)
29 buffer->Indices[i] = u[i];
30
31
32 // Create vertices
33 video::SColor clr(255,255,255,255);
34
35 buffer->Vertices.reallocate(12);
36
37 buffer->Vertices.push_back(video::S3DVertex(0,0,0, -1,-1,-1, clr, 0, 1));
38 buffer->Vertices.push_back(video::S3DVertex(1,0,0, 1,-1,-1, clr, 1, 1));
39 buffer->Vertices.push_back(video::S3DVertex(1,1,0, 1, 1,-1, clr, 1, 0));
40 buffer->Vertices.push_back(video::S3DVertex(0,1,0, -1, 1,-1, clr, 0, 0));
41 buffer->Vertices.push_back(video::S3DVertex(1,0,1, 1,-1, 1, clr, 0, 1));
42 buffer->Vertices.push_back(video::S3DVertex(1,1,1, 1, 1, 1, clr, 0, 0));
43 buffer->Vertices.push_back(video::S3DVertex(0,1,1, -1, 1, 1, clr, 1, 0));
44 buffer->Vertices.push_back(video::S3DVertex(0,0,1, -1,-1, 1, clr, 1, 1));
45 buffer->Vertices.push_back(video::S3DVertex(0,1,1, -1, 1, 1, clr, 0, 1));
46 buffer->Vertices.push_back(video::S3DVertex(0,1,0, -1, 1,-1, clr, 1, 1));
47 buffer->Vertices.push_back(video::S3DVertex(1,0,1, 1,-1, 1, clr, 1, 0));
48 buffer->Vertices.push_back(video::S3DVertex(1,0,0, 1,-1,-1, clr, 0, 0));
49
50 // Recalculate bounding box
51 buffer->BoundingBox.reset(0,0,0);
52
53 for (u32 i=0; i<12; ++i)
54 {
55 buffer->Vertices[i].Pos -= core::vector3df(0.5f, 0.5f, 0.5f);
56 buffer->Vertices[i].Pos *= size;
57 buffer->BoundingBox.addInternalPoint(buffer->Vertices[i].Pos);
58 }
59
60 SMesh* mesh = new SMesh;
61 mesh->addMeshBuffer(buffer);
62 buffer->drop();
63
64 mesh->recalculateBoundingBox();
65 return mesh;
66}
67
68
69// creates a hill plane
70IMesh* CGeometryCreator::createHillPlaneMesh(
71 const core::dimension2d<f32>& tileSize,
72 const core::dimension2d<u32>& tc, video::SMaterial* material,
73 f32 hillHeight, const core::dimension2d<f32>& ch,
74 const core::dimension2d<f32>& textureRepeatCount) const
75{
76 core::dimension2d<u32> tileCount = tc;
77 core::dimension2d<f32> countHills = ch;
78
79 if (countHills.Width < 0.01f)
80 countHills.Width = 1.f;
81 if (countHills.Height < 0.01f)
82 countHills.Height = 1.f;
83
84 // center
85 const core::position2d<f32> center((tileSize.Width * tileCount.Width) * 0.5f, (tileSize.Height * tileCount.Height) * 0.5f);
86
87 // texture coord step
88 const core::dimension2d<f32> tx(
89 textureRepeatCount.Width / tileCount.Width,
90 textureRepeatCount.Height / tileCount.Height);
91
92 // add one more point in each direction for proper tile count
93 ++tileCount.Height;
94 ++tileCount.Width;
95
96 SMeshBuffer* buffer = new SMeshBuffer();
97 video::S3DVertex vtx;
98 vtx.Color.set(255,255,255,255);
99
100 // create vertices from left-front to right-back
101 u32 x;
102
103 f32 sx=0.f, tsx=0.f;
104 for (x=0; x<tileCount.Width; ++x)
105 {
106 f32 sy=0.f, tsy=0.f;
107 for (u32 y=0; y<tileCount.Height; ++y)
108 {
109 vtx.Pos.set(sx - center.X, 0, sy - center.Y);
110 vtx.TCoords.set(tsx, 1.0f - tsy);
111
112 if (core::isnotzero(hillHeight))
113 vtx.Pos.Y = sinf(vtx.Pos.X * countHills.Width * core::PI / center.X) *
114 cosf(vtx.Pos.Z * countHills.Height * core::PI / center.Y) *
115 hillHeight;
116
117 buffer->Vertices.push_back(vtx);
118 sy += tileSize.Height;
119 tsy += tx.Height;
120 }
121 sx += tileSize.Width;
122 tsx += tx.Width;
123 }
124
125 // create indices
126
127 for (x=0; x<tileCount.Width-1; ++x)
128 {
129 for (u32 y=0; y<tileCount.Height-1; ++y)
130 {
131 const s32 current = x*tileCount.Height + y;
132
133 buffer->Indices.push_back(current);
134 buffer->Indices.push_back(current + 1);
135 buffer->Indices.push_back(current + tileCount.Height);
136
137 buffer->Indices.push_back(current + 1);
138 buffer->Indices.push_back(current + 1 + tileCount.Height);
139 buffer->Indices.push_back(current + tileCount.Height);
140 }
141 }
142
143 // recalculate normals
144 for (u32 i=0; i<buffer->Indices.size(); i+=3)
145 {
146 const core::vector3df normal = core::plane3d<f32>(
147 buffer->Vertices[buffer->Indices[i+0]].Pos,
148 buffer->Vertices[buffer->Indices[i+1]].Pos,
149 buffer->Vertices[buffer->Indices[i+2]].Pos).Normal;
150
151 buffer->Vertices[buffer->Indices[i+0]].Normal = normal;
152 buffer->Vertices[buffer->Indices[i+1]].Normal = normal;
153 buffer->Vertices[buffer->Indices[i+2]].Normal = normal;
154 }
155
156 if (material)
157 buffer->Material = *material;
158
159 buffer->recalculateBoundingBox();
160 buffer->setHardwareMappingHint(EHM_STATIC);
161
162 SMesh* mesh = new SMesh();
163 mesh->addMeshBuffer(buffer);
164 mesh->recalculateBoundingBox();
165 buffer->drop();
166 return mesh;
167}
168
169
170IMesh* CGeometryCreator::createTerrainMesh(video::IImage* texture,
171 video::IImage* heightmap, const core::dimension2d<f32>& stretchSize,
172 f32 maxHeight, video::IVideoDriver* driver,
173 const core::dimension2d<u32>& maxVtxBlockSize,
174 bool debugBorders) const
175{
176 if (!texture || !heightmap)
177 return 0;
178
179 // debug border
180 const s32 borderSkip = debugBorders ? 0 : 1;
181
182 video::S3DVertex vtx;
183 vtx.Color.set(255,255,255,255);
184
185 SMesh* mesh = new SMesh();
186
187 const u32 tm = os::Timer::getRealTime()/1000;
188 const core::dimension2d<u32> hMapSize= heightmap->getDimension();
189 const core::dimension2d<u32> tMapSize= texture->getDimension();
190 const core::position2d<f32> thRel(static_cast<f32>(tMapSize.Width) / hMapSize.Width, static_cast<f32>(tMapSize.Height) / hMapSize.Height);
191 maxHeight /= 255.0f; // height step per color value
192
193 core::position2d<u32> processed(0,0);
194 while (processed.Y<hMapSize.Height)
195 {
196 while(processed.X<hMapSize.Width)
197 {
198 core::dimension2d<u32> blockSize = maxVtxBlockSize;
199 if (processed.X + blockSize.Width > hMapSize.Width)
200 blockSize.Width = hMapSize.Width - processed.X;
201 if (processed.Y + blockSize.Height > hMapSize.Height)
202 blockSize.Height = hMapSize.Height - processed.Y;
203
204 SMeshBuffer* buffer = new SMeshBuffer();
205 buffer->setHardwareMappingHint(scene::EHM_STATIC);
206 buffer->Vertices.reallocate(blockSize.getArea());
207 // add vertices of vertex block
208 u32 y;
209 core::vector2df pos(0.f, processed.Y*stretchSize.Height);
210 const core::vector2df bs(1.f/blockSize.Width, 1.f/blockSize.Height);
211 core::vector2df tc(0.f, 0.5f*bs.Y);
212 for (y=0; y<blockSize.Height; ++y)
213 {
214 pos.X=processed.X*stretchSize.Width;
215 tc.X=0.5f*bs.X;
216 for (u32 x=0; x<blockSize.Width; ++x)
217 {
218 const f32 height = heightmap->getPixel(x+processed.X, y+processed.Y).getAverage() * maxHeight;
219
220 vtx.Pos.set(pos.X, height, pos.Y);
221 vtx.TCoords.set(tc);
222 buffer->Vertices.push_back(vtx);
223 pos.X += stretchSize.Width;
224 tc.X += bs.X;
225 }
226 pos.Y += stretchSize.Height;
227 tc.Y += bs.Y;
228 }
229
230 buffer->Indices.reallocate((blockSize.Height-1)*(blockSize.Width-1)*6);
231 // add indices of vertex block
232 s32 c1 = 0;
233 for (y=0; y<blockSize.Height-1; ++y)
234 {
235 for (u32 x=0; x<blockSize.Width-1; ++x)
236 {
237 const s32 c = c1 + x;
238
239 buffer->Indices.push_back(c);
240 buffer->Indices.push_back(c + blockSize.Width);
241 buffer->Indices.push_back(c + 1);
242
243 buffer->Indices.push_back(c + 1);
244 buffer->Indices.push_back(c + blockSize.Width);
245 buffer->Indices.push_back(c + 1 + blockSize.Width);
246 }
247 c1 += blockSize.Width;
248 }
249
250 // recalculate normals
251 for (u32 i=0; i<buffer->Indices.size(); i+=3)
252 {
253 const core::vector3df normal = core::plane3d<f32>(
254 buffer->Vertices[buffer->Indices[i+0]].Pos,
255 buffer->Vertices[buffer->Indices[i+1]].Pos,
256 buffer->Vertices[buffer->Indices[i+2]].Pos).Normal;
257
258 buffer->Vertices[buffer->Indices[i+0]].Normal = normal;
259 buffer->Vertices[buffer->Indices[i+1]].Normal = normal;
260 buffer->Vertices[buffer->Indices[i+2]].Normal = normal;
261 }
262
263 if (buffer->Vertices.size())
264 {
265 c8 textureName[64];
266 // create texture for this block
267 video::IImage* img = driver->createImage(texture->getColorFormat(), core::dimension2d<u32>(core::floor32(blockSize.Width*thRel.X), core::floor32(blockSize.Height*thRel.Y)));
268 texture->copyTo(img, core::position2di(0,0), core::recti(
269 core::position2d<s32>(core::floor32(processed.X*thRel.X), core::floor32(processed.Y*thRel.Y)),
270 core::dimension2d<u32>(core::floor32(blockSize.Width*thRel.X), core::floor32(blockSize.Height*thRel.Y))), 0);
271
272 sprintf(textureName, "terrain%u_%u", tm, mesh->getMeshBufferCount());
273
274 buffer->Material.setTexture(0, driver->addTexture(textureName, img));
275
276 if (buffer->Material.getTexture(0))
277 {
278 c8 tmp[255];
279 sprintf(tmp, "Generated terrain texture (%dx%d): %s",
280 buffer->Material.getTexture(0)->getSize().Width,
281 buffer->Material.getTexture(0)->getSize().Height,
282 textureName);
283 os::Printer::log(tmp);
284 }
285 else
286 os::Printer::log("Could not create terrain texture.", textureName, ELL_ERROR);
287
288 img->drop();
289 }
290
291 buffer->recalculateBoundingBox();
292 mesh->addMeshBuffer(buffer);
293 buffer->drop();
294
295 // keep on processing
296 processed.X += maxVtxBlockSize.Width - borderSkip;
297 }
298
299 // keep on processing
300 processed.X = 0;
301 processed.Y += maxVtxBlockSize.Height - borderSkip;
302 }
303
304 mesh->recalculateBoundingBox();
305 return mesh;
306}
307
308
309/*
310 a cylinder, a cone and a cross
311 point up on (0,1.f, 0.f )
312*/
313IMesh* CGeometryCreator::createArrowMesh(const u32 tesselationCylinder,
314 const u32 tesselationCone,
315 const f32 height,
316 const f32 cylinderHeight,
317 const f32 width0,
318 const f32 width1,
319 const video::SColor vtxColor0,
320 const video::SColor vtxColor1) const
321{
322 SMesh* mesh = (SMesh*)createCylinderMesh(width0, cylinderHeight, tesselationCylinder, vtxColor0, false);
323
324 IMesh* mesh2 = createConeMesh(width1, height-cylinderHeight, tesselationCone, vtxColor1, vtxColor0);
325 for (u32 i=0; i<mesh2->getMeshBufferCount(); ++i)
326 {
327 scene::IMeshBuffer* buffer = mesh2->getMeshBuffer(i);
328 for (u32 j=0; j<buffer->getVertexCount(); ++j)
329 buffer->getPosition(j).Y += cylinderHeight;
330 buffer->setDirty(EBT_VERTEX);
331 buffer->recalculateBoundingBox();
332 mesh->addMeshBuffer(buffer);
333 }
334 mesh2->drop();
335 mesh->setHardwareMappingHint(EHM_STATIC);
336
337 mesh->recalculateBoundingBox();
338 return mesh;
339}
340
341
342/* A sphere with proper normals and texture coords */
343IMesh* CGeometryCreator::createSphereMesh(f32 radius, u32 polyCountX, u32 polyCountY) const
344{
345 // thanks to Alfaz93 who made his code available for Irrlicht on which
346 // this one is based!
347
348 // we are creating the sphere mesh here.
349
350 if (polyCountX < 2)
351 polyCountX = 2;
352 if (polyCountY < 2)
353 polyCountY = 2;
354 while (polyCountX * polyCountY > 32767) // prevent u16 overflow
355 {
356 polyCountX /= 2;
357 polyCountY /= 2;
358 }
359
360 const u32 polyCountXPitch = polyCountX+1; // get to same vertex on next level
361
362 SMeshBuffer* buffer = new SMeshBuffer();
363
364 buffer->Indices.reallocate((polyCountX * polyCountY) * 6);
365
366 const video::SColor clr(255, 255,255,255);
367
368 u32 level = 0;
369
370 for (u32 p1 = 0; p1 < polyCountY-1; ++p1)
371 {
372 //main quads, top to bottom
373 for (u32 p2 = 0; p2 < polyCountX - 1; ++p2)
374 {
375 const u32 curr = level + p2;
376 buffer->Indices.push_back(curr + polyCountXPitch);
377 buffer->Indices.push_back(curr);
378 buffer->Indices.push_back(curr + 1);
379 buffer->Indices.push_back(curr + polyCountXPitch);
380 buffer->Indices.push_back(curr+1);
381 buffer->Indices.push_back(curr + 1 + polyCountXPitch);
382 }
383
384 // the connectors from front to end
385 buffer->Indices.push_back(level + polyCountX - 1 + polyCountXPitch);
386 buffer->Indices.push_back(level + polyCountX - 1);
387 buffer->Indices.push_back(level + polyCountX);
388
389 buffer->Indices.push_back(level + polyCountX - 1 + polyCountXPitch);
390 buffer->Indices.push_back(level + polyCountX);
391 buffer->Indices.push_back(level + polyCountX + polyCountXPitch);
392 level += polyCountXPitch;
393 }
394
395 const u32 polyCountSq = polyCountXPitch * polyCountY; // top point
396 const u32 polyCountSq1 = polyCountSq + 1; // bottom point
397 const u32 polyCountSqM1 = (polyCountY - 1) * polyCountXPitch; // last row's first vertex
398
399 for (u32 p2 = 0; p2 < polyCountX - 1; ++p2)
400 {
401 // create triangles which are at the top of the sphere
402
403 buffer->Indices.push_back(polyCountSq);
404 buffer->Indices.push_back(p2 + 1);
405 buffer->Indices.push_back(p2);
406
407 // create triangles which are at the bottom of the sphere
408
409 buffer->Indices.push_back(polyCountSqM1 + p2);
410 buffer->Indices.push_back(polyCountSqM1 + p2 + 1);
411 buffer->Indices.push_back(polyCountSq1);
412 }
413
414 // create final triangle which is at the top of the sphere
415
416 buffer->Indices.push_back(polyCountSq);
417 buffer->Indices.push_back(polyCountX);
418 buffer->Indices.push_back(polyCountX-1);
419
420 // create final triangle which is at the bottom of the sphere
421
422 buffer->Indices.push_back(polyCountSqM1 + polyCountX - 1);
423 buffer->Indices.push_back(polyCountSqM1);
424 buffer->Indices.push_back(polyCountSq1);
425
426 // calculate the angle which separates all points in a circle
427 const f64 AngleX = 2 * core::PI / polyCountX;
428 const f64 AngleY = core::PI / polyCountY;
429
430 u32 i=0;
431 f64 axz;
432
433 // we don't start at 0.
434
435 f64 ay = 0;//AngleY / 2;
436
437 buffer->Vertices.set_used((polyCountXPitch * polyCountY) + 2);
438 for (u32 y = 0; y < polyCountY; ++y)
439 {
440 ay += AngleY;
441 const f64 sinay = sin(ay);
442 axz = 0;
443
444 // calculate the necessary vertices without the doubled one
445 for (u32 xz = 0;xz < polyCountX; ++xz)
446 {
447 // calculate points position
448
449 const core::vector3df pos(static_cast<f32>(radius * cos(axz) * sinay),
450 static_cast<f32>(radius * cos(ay)),
451 static_cast<f32>(radius * sin(axz) * sinay));
452 // for spheres the normal is the position
453 core::vector3df normal(pos);
454 normal.normalize();
455
456 // calculate texture coordinates via sphere mapping
457 // tu is the same on each level, so only calculate once
458 f32 tu = 0.5f;
459 if (y==0)
460 {
461 if (normal.Y != -1.0f && normal.Y != 1.0f)
462 tu = static_cast<f32>(acos(core::clamp(normal.X/sinay, -1.0, 1.0)) * 0.5 *core::RECIPROCAL_PI64);
463 if (normal.Z < 0.0f)
464 tu=1-tu;
465 }
466 else
467 tu = buffer->Vertices[i-polyCountXPitch].TCoords.X;
468 buffer->Vertices[i] = video::S3DVertex(pos.X, pos.Y, pos.Z,
469 normal.X, normal.Y, normal.Z,
470 clr, tu,
471 static_cast<f32>(ay*core::RECIPROCAL_PI64));
472 ++i;
473 axz += AngleX;
474 }
475 // This is the doubled vertex on the initial position
476 buffer->Vertices[i] = video::S3DVertex(buffer->Vertices[i-polyCountX]);
477 buffer->Vertices[i].TCoords.X=1.0f;
478 ++i;
479 }
480
481 // the vertex at the top of the sphere
482 buffer->Vertices[i] = video::S3DVertex(0.0f,radius,0.0f, 0.0f,1.0f,0.0f, clr, 0.5f, 0.0f);
483
484 // the vertex at the bottom of the sphere
485 ++i;
486 buffer->Vertices[i] = video::S3DVertex(0.0f,-radius,0.0f, 0.0f,-1.0f,0.0f, clr, 0.5f, 1.0f);
487
488 // recalculate bounding box
489
490 buffer->BoundingBox.reset(buffer->Vertices[i].Pos);
491 buffer->BoundingBox.addInternalPoint(buffer->Vertices[i-1].Pos);
492 buffer->BoundingBox.addInternalPoint(radius,0.0f,0.0f);
493 buffer->BoundingBox.addInternalPoint(-radius,0.0f,0.0f);
494 buffer->BoundingBox.addInternalPoint(0.0f,0.0f,radius);
495 buffer->BoundingBox.addInternalPoint(0.0f,0.0f,-radius);
496
497 SMesh* mesh = new SMesh();
498 mesh->addMeshBuffer(buffer);
499 buffer->drop();
500
501 mesh->setHardwareMappingHint(EHM_STATIC);
502 mesh->recalculateBoundingBox();
503 return mesh;
504}
505
506
507/* A cylinder with proper normals and texture coords */
508IMesh* CGeometryCreator::createCylinderMesh(f32 radius, f32 length,
509 u32 tesselation, const video::SColor& color,
510 bool closeTop, f32 oblique) const
511{
512 SMeshBuffer* buffer = new SMeshBuffer();
513
514 const f32 recTesselation = core::reciprocal((f32)tesselation);
515 const f32 recTesselationHalf = recTesselation * 0.5f;
516 const f32 angleStep = (core::PI * 2.f ) * recTesselation;
517 const f32 angleStepHalf = angleStep*0.5f;
518
519 u32 i;
520 video::S3DVertex v;
521 v.Color = color;
522 buffer->Vertices.reallocate(tesselation*4+4+(closeTop?2:1));
523 buffer->Indices.reallocate((tesselation*2+1)*(closeTop?12:9));
524 f32 tcx = 0.f;
525 for ( i = 0; i <= tesselation; ++i )
526 {
527 const f32 angle = angleStep * i;
528 v.Pos.X = radius * cosf(angle);
529 v.Pos.Y = 0.f;
530 v.Pos.Z = radius * sinf(angle);
531 v.Normal = v.Pos;
532 v.Normal.normalize();
533 v.TCoords.X=tcx;
534 v.TCoords.Y=0.f;
535 buffer->Vertices.push_back(v);
536
537 v.Pos.X += oblique;
538 v.Pos.Y = length;
539 v.Normal = v.Pos;
540 v.Normal.normalize();
541 v.TCoords.Y=1.f;
542 buffer->Vertices.push_back(v);
543
544 v.Pos.X = radius * cosf(angle + angleStepHalf);
545 v.Pos.Y = 0.f;
546 v.Pos.Z = radius * sinf(angle + angleStepHalf);
547 v.Normal = v.Pos;
548 v.Normal.normalize();
549 v.TCoords.X=tcx+recTesselationHalf;
550 v.TCoords.Y=0.f;
551 buffer->Vertices.push_back(v);
552
553 v.Pos.X += oblique;
554 v.Pos.Y = length;
555 v.Normal = v.Pos;
556 v.Normal.normalize();
557 v.TCoords.Y=1.f;
558 buffer->Vertices.push_back(v);
559 tcx += recTesselation;
560 }
561
562 // indices for the main hull part
563 const u32 nonWrappedSize = tesselation* 4;
564 for (i=0; i != nonWrappedSize; i += 2)
565 {
566 buffer->Indices.push_back(i + 2);
567 buffer->Indices.push_back(i + 0);
568 buffer->Indices.push_back(i + 1);
569
570 buffer->Indices.push_back(i + 2);
571 buffer->Indices.push_back(i + 1);
572 buffer->Indices.push_back(i + 3);
573 }
574
575 // two closing quads between end and start
576 buffer->Indices.push_back(0);
577 buffer->Indices.push_back(i + 0);
578 buffer->Indices.push_back(i + 1);
579
580 buffer->Indices.push_back(0);
581 buffer->Indices.push_back(i + 1);
582 buffer->Indices.push_back(1);
583
584 // close down
585 v.Pos.X = 0.f;
586 v.Pos.Y = 0.f;
587 v.Pos.Z = 0.f;
588 v.Normal.X = 0.f;
589 v.Normal.Y = -1.f;
590 v.Normal.Z = 0.f;
591 v.TCoords.X = 1.f;
592 v.TCoords.Y = 1.f;
593 buffer->Vertices.push_back(v);
594
595 u32 index = buffer->Vertices.size() - 1;
596
597 for ( i = 0; i != nonWrappedSize; i += 2 )
598 {
599 buffer->Indices.push_back(index);
600 buffer->Indices.push_back(i + 0);
601 buffer->Indices.push_back(i + 2);
602 }
603
604 buffer->Indices.push_back(index);
605 buffer->Indices.push_back(i + 0);
606 buffer->Indices.push_back(0);
607
608 if (closeTop)
609 {
610 // close top
611 v.Pos.X = oblique;
612 v.Pos.Y = length;
613 v.Pos.Z = 0.f;
614 v.Normal.X = 0.f;
615 v.Normal.Y = 1.f;
616 v.Normal.Z = 0.f;
617 v.TCoords.X = 0.f;
618 v.TCoords.Y = 0.f;
619 buffer->Vertices.push_back(v);
620
621 index = buffer->Vertices.size() - 1;
622
623 for ( i = 0; i != nonWrappedSize; i += 2 )
624 {
625 buffer->Indices.push_back(i + 1);
626 buffer->Indices.push_back(index);
627 buffer->Indices.push_back(i + 3);
628 }
629
630 buffer->Indices.push_back(i + 1);
631 buffer->Indices.push_back(index);
632 buffer->Indices.push_back(1);
633 }
634
635 buffer->recalculateBoundingBox();
636 SMesh* mesh = new SMesh();
637 mesh->addMeshBuffer(buffer);
638 mesh->setHardwareMappingHint(EHM_STATIC);
639 mesh->recalculateBoundingBox();
640 buffer->drop();
641 return mesh;
642}
643
644
645/* A cone with proper normals and texture coords */
646IMesh* CGeometryCreator::createConeMesh(f32 radius, f32 length, u32 tesselation,
647 const video::SColor& colorTop,
648 const video::SColor& colorBottom,
649 f32 oblique) const
650{
651 SMeshBuffer* buffer = new SMeshBuffer();
652
653 const f32 angleStep = (core::PI * 2.f ) / tesselation;
654 const f32 angleStepHalf = angleStep*0.5f;
655
656 video::S3DVertex v;
657 u32 i;
658
659 v.Color = colorTop;
660 for ( i = 0; i != tesselation; ++i )
661 {
662 f32 angle = angleStep * f32(i);
663
664 v.Pos.X = radius * cosf(angle);
665 v.Pos.Y = 0.f;
666 v.Pos.Z = radius * sinf(angle);
667 v.Normal = v.Pos;
668 v.Normal.normalize();
669 buffer->Vertices.push_back(v);
670
671 angle += angleStepHalf;
672 v.Pos.X = radius * cosf(angle);
673 v.Pos.Y = 0.f;
674 v.Pos.Z = radius * sinf(angle);
675 v.Normal = v.Pos;
676 v.Normal.normalize();
677 buffer->Vertices.push_back(v);
678 }
679 const u32 nonWrappedSize = buffer->Vertices.size() - 1;
680
681 // close top
682 v.Pos.X = oblique;
683 v.Pos.Y = length;
684 v.Pos.Z = 0.f;
685 v.Normal.X = 0.f;
686 v.Normal.Y = 1.f;
687 v.Normal.Z = 0.f;
688 buffer->Vertices.push_back(v);
689
690 u32 index = buffer->Vertices.size() - 1;
691
692 for ( i = 0; i != nonWrappedSize; i += 1 )
693 {
694 buffer->Indices.push_back(i + 0);
695 buffer->Indices.push_back(index);
696 buffer->Indices.push_back(i + 1);
697 }
698
699 buffer->Indices.push_back(i + 0);
700 buffer->Indices.push_back(index);
701 buffer->Indices.push_back(0);
702
703 // close down
704 v.Color = colorBottom;
705 v.Pos.X = 0.f;
706 v.Pos.Y = 0.f;
707 v.Pos.Z = 0.f;
708 v.Normal.X = 0.f;
709 v.Normal.Y = -1.f;
710 v.Normal.Z = 0.f;
711 buffer->Vertices.push_back(v);
712
713 index = buffer->Vertices.size() - 1;
714
715 for ( i = 0; i != nonWrappedSize; i += 1 )
716 {
717 buffer->Indices.push_back(index);
718 buffer->Indices.push_back(i + 0);
719 buffer->Indices.push_back(i + 1);
720 }
721
722 buffer->Indices.push_back(index);
723 buffer->Indices.push_back(i + 0);
724 buffer->Indices.push_back(0);
725
726 buffer->recalculateBoundingBox();
727 SMesh* mesh = new SMesh();
728 mesh->addMeshBuffer(buffer);
729 buffer->drop();
730
731 mesh->setHardwareMappingHint(EHM_STATIC);
732 mesh->recalculateBoundingBox();
733 return mesh;
734}
735
736
737void CGeometryCreator::addToBuffer(const video::S3DVertex& v, SMeshBuffer* Buffer) const
738{
739 const s32 tnidx = Buffer->Vertices.linear_reverse_search(v);
740 const bool alreadyIn = (tnidx != -1);
741 u16 nidx = (u16)tnidx;
742 if (!alreadyIn)
743 {
744 nidx = (u16)Buffer->Vertices.size();
745 Buffer->Indices.push_back(nidx);
746 Buffer->Vertices.push_back(v);
747 }
748 else
749 Buffer->Indices.push_back(nidx);
750}
751
752
753IMesh* CGeometryCreator::createVolumeLightMesh(
754 const u32 subdivideU, const u32 subdivideV,
755 const video::SColor footColor, const video::SColor tailColor,
756 const f32 lpDistance, const core::vector3df& lightDim) const
757{
758 SMeshBuffer* Buffer = new SMeshBuffer();
759 Buffer->setHardwareMappingHint(EHM_STATIC);
760
761 const core::vector3df lightPoint(0, -(lpDistance*lightDim.Y), 0);
762 const f32 ax = lightDim.X * 0.5f; // X Axis
763 const f32 az = lightDim.Z * 0.5f; // Z Axis
764
765 Buffer->Vertices.clear();
766 Buffer->Vertices.reallocate(6+12*(subdivideU+subdivideV));
767 Buffer->Indices.clear();
768 Buffer->Indices.reallocate(6+12*(subdivideU+subdivideV));
769 //draw the bottom foot.. the glowing region
770 addToBuffer(video::S3DVertex(-ax, 0, az, 0,0,0, footColor, 0, 1),Buffer);
771 addToBuffer(video::S3DVertex( ax, 0, az, 0,0,0, footColor, 1, 1),Buffer);
772 addToBuffer(video::S3DVertex( ax, 0,-az, 0,0,0, footColor, 1, 0),Buffer);
773
774 addToBuffer(video::S3DVertex( ax, 0,-az, 0,0,0, footColor, 1, 0),Buffer);
775 addToBuffer(video::S3DVertex(-ax, 0,-az, 0,0,0, footColor, 0, 0),Buffer);
776 addToBuffer(video::S3DVertex(-ax, 0, az, 0,0,0, footColor, 0, 1),Buffer);
777
778 f32 tu = 0.f;
779 const f32 tuStep = 1.f/subdivideU;
780 f32 bx = -ax;
781 const f32 bxStep = lightDim.X * tuStep;
782 // Slices in X/U space
783 for (u32 i = 0; i <= subdivideU; ++i)
784 {
785 // These are the two endpoints for a slice at the foot
786 core::vector3df end1(bx, 0.0f, -az);
787 core::vector3df end2(bx, 0.0f, az);
788
789 end1 -= lightPoint; // get a vector from point to lightsource
790 end1.normalize(); // normalize vector
791 end1 *= lightDim.Y; // multiply it out by shootlength
792
793 end1.X += bx; // Add the original point location to the vector
794 end1.Z -= az;
795
796 // Do it again for the other point.
797 end2 -= lightPoint;
798 end2.normalize();
799 end2 *= lightDim.Y;
800
801 end2.X += bx;
802 end2.Z += az;
803
804 addToBuffer(video::S3DVertex(bx , 0, az, 0,0,0, footColor, tu, 1),Buffer);
805 addToBuffer(video::S3DVertex(bx , 0, -az, 0,0,0, footColor, tu, 0),Buffer);
806 addToBuffer(video::S3DVertex(end2.X , end2.Y, end2.Z, 0,0,0, tailColor, tu, 1),Buffer);
807
808 addToBuffer(video::S3DVertex(bx , 0, -az, 0,0,0, footColor, tu, 0),Buffer);
809 addToBuffer(video::S3DVertex(end1.X , end1.Y, end1.Z, 0,0,0, tailColor, tu, 0),Buffer);
810 addToBuffer(video::S3DVertex(end2.X , end2.Y, end2.Z, 0,0,0, tailColor, tu, 1),Buffer);
811
812 //back side
813 addToBuffer(video::S3DVertex(-end2.X , end2.Y, -end2.Z, 0,0,0, tailColor, tu, 1),Buffer);
814 addToBuffer(video::S3DVertex(-bx , 0, -az, 0,0,0, footColor, tu, 1),Buffer);
815 addToBuffer(video::S3DVertex(-bx , 0, az, 0,0,0, footColor, tu, 0),Buffer);
816
817 addToBuffer(video::S3DVertex(-bx , 0, az, 0,0,0, footColor, tu, 0),Buffer);
818 addToBuffer(video::S3DVertex(-end1.X , end1.Y, -end1.Z, 0,0,0, tailColor, tu, 0),Buffer);
819 addToBuffer(video::S3DVertex(-end2.X , end2.Y, -end2.Z, 0,0,0, tailColor, tu, 1),Buffer);
820 tu += tuStep;
821 bx += bxStep;
822 }
823
824 f32 tv = 0.f;
825 const f32 tvStep = 1.f/subdivideV;
826 f32 bz = -az;
827 const f32 bzStep = lightDim.Z * tvStep;
828 // Slices in Z/V space
829 for(u32 i = 0; i <= subdivideV; ++i)
830 {
831 // These are the two endpoints for a slice at the foot
832 core::vector3df end1(-ax, 0.0f, bz);
833 core::vector3df end2(ax, 0.0f, bz);
834
835 end1 -= lightPoint; // get a vector from point to lightsource
836 end1.normalize(); // normalize vector
837 end1 *= lightDim.Y; // multiply it out by shootlength
838
839 end1.X -= ax; // Add the original point location to the vector
840 end1.Z += bz;
841
842 // Do it again for the other point.
843 end2 -= lightPoint;
844 end2.normalize();
845 end2 *= lightDim.Y;
846
847 end2.X += ax;
848 end2.Z += bz;
849
850 addToBuffer(video::S3DVertex(-ax , 0, bz, 0,0,0, footColor, 0, tv),Buffer);
851 addToBuffer(video::S3DVertex(ax , 0, bz, 0,0,0, footColor, 1, tv),Buffer);
852 addToBuffer(video::S3DVertex(end2.X , end2.Y, end2.Z, 0,0,0, tailColor, 1, tv),Buffer);
853
854 addToBuffer(video::S3DVertex(end2.X , end2.Y, end2.Z, 0,0,0, tailColor, 1, tv),Buffer);
855 addToBuffer(video::S3DVertex(end1.X , end1.Y, end1.Z, 0,0,0, tailColor, 0, tv),Buffer);
856 addToBuffer(video::S3DVertex(-ax , 0, bz, 0,0,0, footColor, 0, tv),Buffer);
857
858 //back side
859 addToBuffer(video::S3DVertex(ax , 0, -bz, 0,0,0, footColor, 0, tv),Buffer);
860 addToBuffer(video::S3DVertex(-ax , 0, -bz, 0,0,0, footColor, 1, tv),Buffer);
861 addToBuffer(video::S3DVertex(-end2.X , end2.Y, -end2.Z, 0,0,0, tailColor, 1, tv),Buffer);
862
863 addToBuffer(video::S3DVertex(-end2.X , end2.Y, -end2.Z, 0,0,0, tailColor, 1, tv),Buffer);
864 addToBuffer(video::S3DVertex(-end1.X , end1.Y, -end1.Z, 0,0,0, tailColor, 0, tv),Buffer);
865 addToBuffer(video::S3DVertex(ax , 0, -bz, 0,0,0, footColor, 0, tv),Buffer);
866 tv += tvStep;
867 bz += bzStep;
868 }
869
870 Buffer->recalculateBoundingBox();
871
872 Buffer->Material.MaterialType = video::EMT_ONETEXTURE_BLEND;
873 Buffer->Material.MaterialTypeParam = pack_textureBlendFunc( video::EBF_SRC_COLOR, video::EBF_SRC_ALPHA, video::EMFN_MODULATE_1X );
874
875 Buffer->Material.Lighting = false;
876 Buffer->Material.ZWriteEnable = false;
877
878 Buffer->setDirty(EBT_VERTEX_AND_INDEX);
879
880 Buffer->recalculateBoundingBox();
881 SMesh* mesh = new SMesh();
882 mesh->addMeshBuffer(Buffer);
883 Buffer->drop();
884
885 mesh->recalculateBoundingBox();
886 return mesh;
887}
888
889
890} // end namespace scene
891} // end namespace irr
892