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