aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/irrlicht-1.8/source/Irrlicht/CMeshManipulator.cpp
diff options
context:
space:
mode:
authorDavid Walter Seikel2013-01-13 18:54:10 +1000
committerDavid Walter Seikel2013-01-13 18:54:10 +1000
commit959831f4ef5a3e797f576c3de08cd65032c997ad (patch)
treee7351908be5995f0b325b2ebeaa02d5a34b82583 /libraries/irrlicht-1.8/source/Irrlicht/CMeshManipulator.cpp
parentAdd info about changes to Irrlicht. (diff)
downloadSledjHamr-959831f4ef5a3e797f576c3de08cd65032c997ad.zip
SledjHamr-959831f4ef5a3e797f576c3de08cd65032c997ad.tar.gz
SledjHamr-959831f4ef5a3e797f576c3de08cd65032c997ad.tar.bz2
SledjHamr-959831f4ef5a3e797f576c3de08cd65032c997ad.tar.xz
Remove damned ancient DOS line endings from Irrlicht. Hopefully I did not go overboard.
Diffstat (limited to '')
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/CMeshManipulator.cpp3640
1 files changed, 1820 insertions, 1820 deletions
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/CMeshManipulator.cpp b/libraries/irrlicht-1.8/source/Irrlicht/CMeshManipulator.cpp
index db9ecf3..c803226 100644
--- a/libraries/irrlicht-1.8/source/Irrlicht/CMeshManipulator.cpp
+++ b/libraries/irrlicht-1.8/source/Irrlicht/CMeshManipulator.cpp
@@ -1,1820 +1,1820 @@
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 "CMeshManipulator.h" 5#include "CMeshManipulator.h"
6#include "SMesh.h" 6#include "SMesh.h"
7#include "CMeshBuffer.h" 7#include "CMeshBuffer.h"
8#include "SAnimatedMesh.h" 8#include "SAnimatedMesh.h"
9#include "os.h" 9#include "os.h"
10#include "irrMap.h" 10#include "irrMap.h"
11 11
12namespace irr 12namespace irr
13{ 13{
14namespace scene 14namespace scene
15{ 15{
16 16
17static inline core::vector3df getAngleWeight(const core::vector3df& v1, 17static inline core::vector3df getAngleWeight(const core::vector3df& v1,
18 const core::vector3df& v2, 18 const core::vector3df& v2,
19 const core::vector3df& v3) 19 const core::vector3df& v3)
20{ 20{
21 // Calculate this triangle's weight for each of its three vertices 21 // Calculate this triangle's weight for each of its three vertices
22 // start by calculating the lengths of its sides 22 // start by calculating the lengths of its sides
23 const f32 a = v2.getDistanceFromSQ(v3); 23 const f32 a = v2.getDistanceFromSQ(v3);
24 const f32 asqrt = sqrtf(a); 24 const f32 asqrt = sqrtf(a);
25 const f32 b = v1.getDistanceFromSQ(v3); 25 const f32 b = v1.getDistanceFromSQ(v3);
26 const f32 bsqrt = sqrtf(b); 26 const f32 bsqrt = sqrtf(b);
27 const f32 c = v1.getDistanceFromSQ(v2); 27 const f32 c = v1.getDistanceFromSQ(v2);
28 const f32 csqrt = sqrtf(c); 28 const f32 csqrt = sqrtf(c);
29 29
30 // use them to find the angle at each vertex 30 // use them to find the angle at each vertex
31 return core::vector3df( 31 return core::vector3df(
32 acosf((b + c - a) / (2.f * bsqrt * csqrt)), 32 acosf((b + c - a) / (2.f * bsqrt * csqrt)),
33 acosf((-b + c + a) / (2.f * asqrt * csqrt)), 33 acosf((-b + c + a) / (2.f * asqrt * csqrt)),
34 acosf((b - c + a) / (2.f * bsqrt * asqrt))); 34 acosf((b - c + a) / (2.f * bsqrt * asqrt)));
35} 35}
36 36
37 37
38//! Flips the direction of surfaces. Changes backfacing triangles to frontfacing 38//! Flips the direction of surfaces. Changes backfacing triangles to frontfacing
39//! triangles and vice versa. 39//! triangles and vice versa.
40//! \param mesh: Mesh on which the operation is performed. 40//! \param mesh: Mesh on which the operation is performed.
41void CMeshManipulator::flipSurfaces(scene::IMesh* mesh) const 41void CMeshManipulator::flipSurfaces(scene::IMesh* mesh) const
42{ 42{
43 if (!mesh) 43 if (!mesh)
44 return; 44 return;
45 45
46 const u32 bcount = mesh->getMeshBufferCount(); 46 const u32 bcount = mesh->getMeshBufferCount();
47 for (u32 b=0; b<bcount; ++b) 47 for (u32 b=0; b<bcount; ++b)
48 { 48 {
49 IMeshBuffer* buffer = mesh->getMeshBuffer(b); 49 IMeshBuffer* buffer = mesh->getMeshBuffer(b);
50 const u32 idxcnt = buffer->getIndexCount(); 50 const u32 idxcnt = buffer->getIndexCount();
51 if (buffer->getIndexType() == video::EIT_16BIT) 51 if (buffer->getIndexType() == video::EIT_16BIT)
52 { 52 {
53 u16* idx = buffer->getIndices(); 53 u16* idx = buffer->getIndices();
54 for (u32 i=0; i<idxcnt; i+=3) 54 for (u32 i=0; i<idxcnt; i+=3)
55 { 55 {
56 const u16 tmp = idx[i+1]; 56 const u16 tmp = idx[i+1];
57 idx[i+1] = idx[i+2]; 57 idx[i+1] = idx[i+2];
58 idx[i+2] = tmp; 58 idx[i+2] = tmp;
59 } 59 }
60 } 60 }
61 else 61 else
62 { 62 {
63 u32* idx = reinterpret_cast<u32*>(buffer->getIndices()); 63 u32* idx = reinterpret_cast<u32*>(buffer->getIndices());
64 for (u32 i=0; i<idxcnt; i+=3) 64 for (u32 i=0; i<idxcnt; i+=3)
65 { 65 {
66 const u32 tmp = idx[i+1]; 66 const u32 tmp = idx[i+1];
67 idx[i+1] = idx[i+2]; 67 idx[i+1] = idx[i+2];
68 idx[i+2] = tmp; 68 idx[i+2] = tmp;
69 } 69 }
70 } 70 }
71 } 71 }
72} 72}
73 73
74 74
75namespace 75namespace
76{ 76{
77template <typename T> 77template <typename T>
78void recalculateNormalsT(IMeshBuffer* buffer, bool smooth, bool angleWeighted) 78void recalculateNormalsT(IMeshBuffer* buffer, bool smooth, bool angleWeighted)
79{ 79{
80 const u32 vtxcnt = buffer->getVertexCount(); 80 const u32 vtxcnt = buffer->getVertexCount();
81 const u32 idxcnt = buffer->getIndexCount(); 81 const u32 idxcnt = buffer->getIndexCount();
82 const T* idx = reinterpret_cast<T*>(buffer->getIndices()); 82 const T* idx = reinterpret_cast<T*>(buffer->getIndices());
83 83
84 if (!smooth) 84 if (!smooth)
85 { 85 {
86 for (u32 i=0; i<idxcnt; i+=3) 86 for (u32 i=0; i<idxcnt; i+=3)
87 { 87 {
88 const core::vector3df& v1 = buffer->getPosition(idx[i+0]); 88 const core::vector3df& v1 = buffer->getPosition(idx[i+0]);
89 const core::vector3df& v2 = buffer->getPosition(idx[i+1]); 89 const core::vector3df& v2 = buffer->getPosition(idx[i+1]);
90 const core::vector3df& v3 = buffer->getPosition(idx[i+2]); 90 const core::vector3df& v3 = buffer->getPosition(idx[i+2]);
91 const core::vector3df normal = core::plane3d<f32>(v1, v2, v3).Normal; 91 const core::vector3df normal = core::plane3d<f32>(v1, v2, v3).Normal;
92 buffer->getNormal(idx[i+0]) = normal; 92 buffer->getNormal(idx[i+0]) = normal;
93 buffer->getNormal(idx[i+1]) = normal; 93 buffer->getNormal(idx[i+1]) = normal;
94 buffer->getNormal(idx[i+2]) = normal; 94 buffer->getNormal(idx[i+2]) = normal;
95 } 95 }
96 } 96 }
97 else 97 else
98 { 98 {
99 u32 i; 99 u32 i;
100 100
101 for ( i = 0; i!= vtxcnt; ++i ) 101 for ( i = 0; i!= vtxcnt; ++i )
102 buffer->getNormal(i).set(0.f, 0.f, 0.f); 102 buffer->getNormal(i).set(0.f, 0.f, 0.f);
103 103
104 for ( i=0; i<idxcnt; i+=3) 104 for ( i=0; i<idxcnt; i+=3)
105 { 105 {
106 const core::vector3df& v1 = buffer->getPosition(idx[i+0]); 106 const core::vector3df& v1 = buffer->getPosition(idx[i+0]);
107 const core::vector3df& v2 = buffer->getPosition(idx[i+1]); 107 const core::vector3df& v2 = buffer->getPosition(idx[i+1]);
108 const core::vector3df& v3 = buffer->getPosition(idx[i+2]); 108 const core::vector3df& v3 = buffer->getPosition(idx[i+2]);
109 const core::vector3df normal = core::plane3d<f32>(v1, v2, v3).Normal; 109 const core::vector3df normal = core::plane3d<f32>(v1, v2, v3).Normal;
110 110
111 core::vector3df weight(1.f,1.f,1.f); 111 core::vector3df weight(1.f,1.f,1.f);
112 if (angleWeighted) 112 if (angleWeighted)
113 weight = getAngleWeight(v1,v2,v3); 113 weight = getAngleWeight(v1,v2,v3);
114 114
115 buffer->getNormal(idx[i+0]) += weight.X*normal; 115 buffer->getNormal(idx[i+0]) += weight.X*normal;
116 buffer->getNormal(idx[i+1]) += weight.Y*normal; 116 buffer->getNormal(idx[i+1]) += weight.Y*normal;
117 buffer->getNormal(idx[i+2]) += weight.Z*normal; 117 buffer->getNormal(idx[i+2]) += weight.Z*normal;
118 } 118 }
119 119
120 for ( i = 0; i!= vtxcnt; ++i ) 120 for ( i = 0; i!= vtxcnt; ++i )
121 buffer->getNormal(i).normalize(); 121 buffer->getNormal(i).normalize();
122 } 122 }
123} 123}
124} 124}
125 125
126 126
127//! Recalculates all normals of the mesh buffer. 127//! Recalculates all normals of the mesh buffer.
128/** \param buffer: Mesh buffer on which the operation is performed. */ 128/** \param buffer: Mesh buffer on which the operation is performed. */
129void CMeshManipulator::recalculateNormals(IMeshBuffer* buffer, bool smooth, bool angleWeighted) const 129void CMeshManipulator::recalculateNormals(IMeshBuffer* buffer, bool smooth, bool angleWeighted) const
130{ 130{
131 if (!buffer) 131 if (!buffer)
132 return; 132 return;
133 133
134 if (buffer->getIndexType()==video::EIT_16BIT) 134 if (buffer->getIndexType()==video::EIT_16BIT)
135 recalculateNormalsT<u16>(buffer, smooth, angleWeighted); 135 recalculateNormalsT<u16>(buffer, smooth, angleWeighted);
136 else 136 else
137 recalculateNormalsT<u32>(buffer, smooth, angleWeighted); 137 recalculateNormalsT<u32>(buffer, smooth, angleWeighted);
138} 138}
139 139
140 140
141//! Recalculates all normals of the mesh. 141//! Recalculates all normals of the mesh.
142//! \param mesh: Mesh on which the operation is performed. 142//! \param mesh: Mesh on which the operation is performed.
143void CMeshManipulator::recalculateNormals(scene::IMesh* mesh, bool smooth, bool angleWeighted) const 143void CMeshManipulator::recalculateNormals(scene::IMesh* mesh, bool smooth, bool angleWeighted) const
144{ 144{
145 if (!mesh) 145 if (!mesh)
146 return; 146 return;
147 147
148 const u32 bcount = mesh->getMeshBufferCount(); 148 const u32 bcount = mesh->getMeshBufferCount();
149 for ( u32 b=0; b<bcount; ++b) 149 for ( u32 b=0; b<bcount; ++b)
150 recalculateNormals(mesh->getMeshBuffer(b), smooth, angleWeighted); 150 recalculateNormals(mesh->getMeshBuffer(b), smooth, angleWeighted);
151} 151}
152 152
153 153
154namespace 154namespace
155{ 155{
156void calculateTangents( 156void calculateTangents(
157 core::vector3df& normal, 157 core::vector3df& normal,
158 core::vector3df& tangent, 158 core::vector3df& tangent,
159 core::vector3df& binormal, 159 core::vector3df& binormal,
160 const core::vector3df& vt1, const core::vector3df& vt2, const core::vector3df& vt3, // vertices 160 const core::vector3df& vt1, const core::vector3df& vt2, const core::vector3df& vt3, // vertices
161 const core::vector2df& tc1, const core::vector2df& tc2, const core::vector2df& tc3) // texture coords 161 const core::vector2df& tc1, const core::vector2df& tc2, const core::vector2df& tc3) // texture coords
162{ 162{
163 // choose one of them: 163 // choose one of them:
164 //#define USE_NVIDIA_GLH_VERSION // use version used by nvidia in glh headers 164 //#define USE_NVIDIA_GLH_VERSION // use version used by nvidia in glh headers
165 #define USE_IRR_VERSION 165 #define USE_IRR_VERSION
166 166
167#ifdef USE_IRR_VERSION 167#ifdef USE_IRR_VERSION
168 168
169 core::vector3df v1 = vt1 - vt2; 169 core::vector3df v1 = vt1 - vt2;
170 core::vector3df v2 = vt3 - vt1; 170 core::vector3df v2 = vt3 - vt1;
171 normal = v2.crossProduct(v1); 171 normal = v2.crossProduct(v1);
172 normal.normalize(); 172 normal.normalize();
173 173
174 // binormal 174 // binormal
175 175
176 f32 deltaX1 = tc1.X - tc2.X; 176 f32 deltaX1 = tc1.X - tc2.X;
177 f32 deltaX2 = tc3.X - tc1.X; 177 f32 deltaX2 = tc3.X - tc1.X;
178 binormal = (v1 * deltaX2) - (v2 * deltaX1); 178 binormal = (v1 * deltaX2) - (v2 * deltaX1);
179 binormal.normalize(); 179 binormal.normalize();
180 180
181 // tangent 181 // tangent
182 182
183 f32 deltaY1 = tc1.Y - tc2.Y; 183 f32 deltaY1 = tc1.Y - tc2.Y;
184 f32 deltaY2 = tc3.Y - tc1.Y; 184 f32 deltaY2 = tc3.Y - tc1.Y;
185 tangent = (v1 * deltaY2) - (v2 * deltaY1); 185 tangent = (v1 * deltaY2) - (v2 * deltaY1);
186 tangent.normalize(); 186 tangent.normalize();
187 187
188 // adjust 188 // adjust
189 189
190 core::vector3df txb = tangent.crossProduct(binormal); 190 core::vector3df txb = tangent.crossProduct(binormal);
191 if (txb.dotProduct(normal) < 0.0f) 191 if (txb.dotProduct(normal) < 0.0f)
192 { 192 {
193 tangent *= -1.0f; 193 tangent *= -1.0f;
194 binormal *= -1.0f; 194 binormal *= -1.0f;
195 } 195 }
196 196
197#endif // USE_IRR_VERSION 197#endif // USE_IRR_VERSION
198 198
199#ifdef USE_NVIDIA_GLH_VERSION 199#ifdef USE_NVIDIA_GLH_VERSION
200 200
201 tangent.set(0,0,0); 201 tangent.set(0,0,0);
202 binormal.set(0,0,0); 202 binormal.set(0,0,0);
203 203
204 core::vector3df v1(vt2.X - vt1.X, tc2.X - tc1.X, tc2.Y - tc1.Y); 204 core::vector3df v1(vt2.X - vt1.X, tc2.X - tc1.X, tc2.Y - tc1.Y);
205 core::vector3df v2(vt3.X - vt1.X, tc3.X - tc1.X, tc3.Y - tc1.Y); 205 core::vector3df v2(vt3.X - vt1.X, tc3.X - tc1.X, tc3.Y - tc1.Y);
206 206
207 core::vector3df txb = v1.crossProduct(v2); 207 core::vector3df txb = v1.crossProduct(v2);
208 if ( !core::iszero ( txb.X ) ) 208 if ( !core::iszero ( txb.X ) )
209 { 209 {
210 tangent.X = -txb.Y / txb.X; 210 tangent.X = -txb.Y / txb.X;
211 binormal.X = -txb.Z / txb.X; 211 binormal.X = -txb.Z / txb.X;
212 } 212 }
213 213
214 v1.X = vt2.Y - vt1.Y; 214 v1.X = vt2.Y - vt1.Y;
215 v2.X = vt3.Y - vt1.Y; 215 v2.X = vt3.Y - vt1.Y;
216 txb = v1.crossProduct(v2); 216 txb = v1.crossProduct(v2);
217 217
218 if ( !core::iszero ( txb.X ) ) 218 if ( !core::iszero ( txb.X ) )
219 { 219 {
220 tangent.Y = -txb.Y / txb.X; 220 tangent.Y = -txb.Y / txb.X;
221 binormal.Y = -txb.Z / txb.X; 221 binormal.Y = -txb.Z / txb.X;
222 } 222 }
223 223
224 v1.X = vt2.Z - vt1.Z; 224 v1.X = vt2.Z - vt1.Z;
225 v2.X = vt3.Z - vt1.Z; 225 v2.X = vt3.Z - vt1.Z;
226 txb = v1.crossProduct(v2); 226 txb = v1.crossProduct(v2);
227 227
228 if ( !core::iszero ( txb.X ) ) 228 if ( !core::iszero ( txb.X ) )
229 { 229 {
230 tangent.Z = -txb.Y / txb.X; 230 tangent.Z = -txb.Y / txb.X;
231 binormal.Z = -txb.Z / txb.X; 231 binormal.Z = -txb.Z / txb.X;
232 } 232 }
233 233
234 tangent.normalize(); 234 tangent.normalize();
235 binormal.normalize(); 235 binormal.normalize();
236 236
237 normal = tangent.crossProduct(binormal); 237 normal = tangent.crossProduct(binormal);
238 normal.normalize(); 238 normal.normalize();
239 239
240 binormal = tangent.crossProduct(normal); 240 binormal = tangent.crossProduct(normal);
241 binormal.normalize(); 241 binormal.normalize();
242 242
243 core::plane3d<f32> pl(vt1, vt2, vt3); 243 core::plane3d<f32> pl(vt1, vt2, vt3);
244 244
245 if(normal.dotProduct(pl.Normal) < 0.0f ) 245 if(normal.dotProduct(pl.Normal) < 0.0f )
246 normal *= -1.0f; 246 normal *= -1.0f;
247 247
248#endif // USE_NVIDIA_GLH_VERSION 248#endif // USE_NVIDIA_GLH_VERSION
249} 249}
250 250
251 251
252//! Recalculates tangents for a tangent mesh buffer 252//! Recalculates tangents for a tangent mesh buffer
253template <typename T> 253template <typename T>
254void recalculateTangentsT(IMeshBuffer* buffer, bool recalculateNormals, bool smooth, bool angleWeighted) 254void recalculateTangentsT(IMeshBuffer* buffer, bool recalculateNormals, bool smooth, bool angleWeighted)
255{ 255{
256 if (!buffer || (buffer->getVertexType()!= video::EVT_TANGENTS)) 256 if (!buffer || (buffer->getVertexType()!= video::EVT_TANGENTS))
257 return; 257 return;
258 258
259 const u32 vtxCnt = buffer->getVertexCount(); 259 const u32 vtxCnt = buffer->getVertexCount();
260 const u32 idxCnt = buffer->getIndexCount(); 260 const u32 idxCnt = buffer->getIndexCount();
261 261
262 T* idx = reinterpret_cast<T*>(buffer->getIndices()); 262 T* idx = reinterpret_cast<T*>(buffer->getIndices());
263 video::S3DVertexTangents* v = 263 video::S3DVertexTangents* v =
264 (video::S3DVertexTangents*)buffer->getVertices(); 264 (video::S3DVertexTangents*)buffer->getVertices();
265 265
266 if (smooth) 266 if (smooth)
267 { 267 {
268 u32 i; 268 u32 i;
269 269
270 for ( i = 0; i!= vtxCnt; ++i ) 270 for ( i = 0; i!= vtxCnt; ++i )
271 { 271 {
272 if (recalculateNormals) 272 if (recalculateNormals)
273 v[i].Normal.set( 0.f, 0.f, 0.f ); 273 v[i].Normal.set( 0.f, 0.f, 0.f );
274 v[i].Tangent.set( 0.f, 0.f, 0.f ); 274 v[i].Tangent.set( 0.f, 0.f, 0.f );
275 v[i].Binormal.set( 0.f, 0.f, 0.f ); 275 v[i].Binormal.set( 0.f, 0.f, 0.f );
276 } 276 }
277 277
278 //Each vertex gets the sum of the tangents and binormals from the faces around it 278 //Each vertex gets the sum of the tangents and binormals from the faces around it
279 for ( i=0; i<idxCnt; i+=3) 279 for ( i=0; i<idxCnt; i+=3)
280 { 280 {
281 // if this triangle is degenerate, skip it! 281 // if this triangle is degenerate, skip it!
282 if (v[idx[i+0]].Pos == v[idx[i+1]].Pos || 282 if (v[idx[i+0]].Pos == v[idx[i+1]].Pos ||
283 v[idx[i+0]].Pos == v[idx[i+2]].Pos || 283 v[idx[i+0]].Pos == v[idx[i+2]].Pos ||
284 v[idx[i+1]].Pos == v[idx[i+2]].Pos 284 v[idx[i+1]].Pos == v[idx[i+2]].Pos
285 /*|| 285 /*||
286 v[idx[i+0]].TCoords == v[idx[i+1]].TCoords || 286 v[idx[i+0]].TCoords == v[idx[i+1]].TCoords ||
287 v[idx[i+0]].TCoords == v[idx[i+2]].TCoords || 287 v[idx[i+0]].TCoords == v[idx[i+2]].TCoords ||
288 v[idx[i+1]].TCoords == v[idx[i+2]].TCoords */ 288 v[idx[i+1]].TCoords == v[idx[i+2]].TCoords */
289 ) 289 )
290 continue; 290 continue;
291 291
292 //Angle-weighted normals look better, but are slightly more CPU intensive to calculate 292 //Angle-weighted normals look better, but are slightly more CPU intensive to calculate
293 core::vector3df weight(1.f,1.f,1.f); 293 core::vector3df weight(1.f,1.f,1.f);
294 if (angleWeighted) 294 if (angleWeighted)
295 weight = getAngleWeight(v[i+0].Pos,v[i+1].Pos,v[i+2].Pos); 295 weight = getAngleWeight(v[i+0].Pos,v[i+1].Pos,v[i+2].Pos);
296 core::vector3df localNormal; 296 core::vector3df localNormal;
297 core::vector3df localTangent; 297 core::vector3df localTangent;
298 core::vector3df localBinormal; 298 core::vector3df localBinormal;
299 299
300 calculateTangents( 300 calculateTangents(
301 localNormal, 301 localNormal,
302 localTangent, 302 localTangent,
303 localBinormal, 303 localBinormal,
304 v[idx[i+0]].Pos, 304 v[idx[i+0]].Pos,
305 v[idx[i+1]].Pos, 305 v[idx[i+1]].Pos,
306 v[idx[i+2]].Pos, 306 v[idx[i+2]].Pos,
307 v[idx[i+0]].TCoords, 307 v[idx[i+0]].TCoords,
308 v[idx[i+1]].TCoords, 308 v[idx[i+1]].TCoords,
309 v[idx[i+2]].TCoords); 309 v[idx[i+2]].TCoords);
310 310
311 if (recalculateNormals) 311 if (recalculateNormals)
312 v[idx[i+0]].Normal += localNormal * weight.X; 312 v[idx[i+0]].Normal += localNormal * weight.X;
313 v[idx[i+0]].Tangent += localTangent * weight.X; 313 v[idx[i+0]].Tangent += localTangent * weight.X;
314 v[idx[i+0]].Binormal += localBinormal * weight.X; 314 v[idx[i+0]].Binormal += localBinormal * weight.X;
315 315
316 calculateTangents( 316 calculateTangents(
317 localNormal, 317 localNormal,
318 localTangent, 318 localTangent,
319 localBinormal, 319 localBinormal,
320 v[idx[i+1]].Pos, 320 v[idx[i+1]].Pos,
321 v[idx[i+2]].Pos, 321 v[idx[i+2]].Pos,
322 v[idx[i+0]].Pos, 322 v[idx[i+0]].Pos,
323 v[idx[i+1]].TCoords, 323 v[idx[i+1]].TCoords,
324 v[idx[i+2]].TCoords, 324 v[idx[i+2]].TCoords,
325 v[idx[i+0]].TCoords); 325 v[idx[i+0]].TCoords);
326 326
327 if (recalculateNormals) 327 if (recalculateNormals)
328 v[idx[i+1]].Normal += localNormal * weight.Y; 328 v[idx[i+1]].Normal += localNormal * weight.Y;
329 v[idx[i+1]].Tangent += localTangent * weight.Y; 329 v[idx[i+1]].Tangent += localTangent * weight.Y;
330 v[idx[i+1]].Binormal += localBinormal * weight.Y; 330 v[idx[i+1]].Binormal += localBinormal * weight.Y;
331 331
332 calculateTangents( 332 calculateTangents(
333 localNormal, 333 localNormal,
334 localTangent, 334 localTangent,
335 localBinormal, 335 localBinormal,
336 v[idx[i+2]].Pos, 336 v[idx[i+2]].Pos,
337 v[idx[i+0]].Pos, 337 v[idx[i+0]].Pos,
338 v[idx[i+1]].Pos, 338 v[idx[i+1]].Pos,
339 v[idx[i+2]].TCoords, 339 v[idx[i+2]].TCoords,
340 v[idx[i+0]].TCoords, 340 v[idx[i+0]].TCoords,
341 v[idx[i+1]].TCoords); 341 v[idx[i+1]].TCoords);
342 342
343 if (recalculateNormals) 343 if (recalculateNormals)
344 v[idx[i+2]].Normal += localNormal * weight.Z; 344 v[idx[i+2]].Normal += localNormal * weight.Z;
345 v[idx[i+2]].Tangent += localTangent * weight.Z; 345 v[idx[i+2]].Tangent += localTangent * weight.Z;
346 v[idx[i+2]].Binormal += localBinormal * weight.Z; 346 v[idx[i+2]].Binormal += localBinormal * weight.Z;
347 } 347 }
348 348
349 // Normalize the tangents and binormals 349 // Normalize the tangents and binormals
350 if (recalculateNormals) 350 if (recalculateNormals)
351 { 351 {
352 for ( i = 0; i!= vtxCnt; ++i ) 352 for ( i = 0; i!= vtxCnt; ++i )
353 v[i].Normal.normalize(); 353 v[i].Normal.normalize();
354 } 354 }
355 for ( i = 0; i!= vtxCnt; ++i ) 355 for ( i = 0; i!= vtxCnt; ++i )
356 { 356 {
357 v[i].Tangent.normalize(); 357 v[i].Tangent.normalize();
358 v[i].Binormal.normalize(); 358 v[i].Binormal.normalize();
359 } 359 }
360 } 360 }
361 else 361 else
362 { 362 {
363 core::vector3df localNormal; 363 core::vector3df localNormal;
364 for (u32 i=0; i<idxCnt; i+=3) 364 for (u32 i=0; i<idxCnt; i+=3)
365 { 365 {
366 calculateTangents( 366 calculateTangents(
367 localNormal, 367 localNormal,
368 v[idx[i+0]].Tangent, 368 v[idx[i+0]].Tangent,
369 v[idx[i+0]].Binormal, 369 v[idx[i+0]].Binormal,
370 v[idx[i+0]].Pos, 370 v[idx[i+0]].Pos,
371 v[idx[i+1]].Pos, 371 v[idx[i+1]].Pos,
372 v[idx[i+2]].Pos, 372 v[idx[i+2]].Pos,
373 v[idx[i+0]].TCoords, 373 v[idx[i+0]].TCoords,
374 v[idx[i+1]].TCoords, 374 v[idx[i+1]].TCoords,
375 v[idx[i+2]].TCoords); 375 v[idx[i+2]].TCoords);
376 if (recalculateNormals) 376 if (recalculateNormals)
377 v[idx[i+0]].Normal=localNormal; 377 v[idx[i+0]].Normal=localNormal;
378 378
379 calculateTangents( 379 calculateTangents(
380 localNormal, 380 localNormal,
381 v[idx[i+1]].Tangent, 381 v[idx[i+1]].Tangent,
382 v[idx[i+1]].Binormal, 382 v[idx[i+1]].Binormal,
383 v[idx[i+1]].Pos, 383 v[idx[i+1]].Pos,
384 v[idx[i+2]].Pos, 384 v[idx[i+2]].Pos,
385 v[idx[i+0]].Pos, 385 v[idx[i+0]].Pos,
386 v[idx[i+1]].TCoords, 386 v[idx[i+1]].TCoords,
387 v[idx[i+2]].TCoords, 387 v[idx[i+2]].TCoords,
388 v[idx[i+0]].TCoords); 388 v[idx[i+0]].TCoords);
389 if (recalculateNormals) 389 if (recalculateNormals)
390 v[idx[i+1]].Normal=localNormal; 390 v[idx[i+1]].Normal=localNormal;
391 391
392 calculateTangents( 392 calculateTangents(
393 localNormal, 393 localNormal,
394 v[idx[i+2]].Tangent, 394 v[idx[i+2]].Tangent,
395 v[idx[i+2]].Binormal, 395 v[idx[i+2]].Binormal,
396 v[idx[i+2]].Pos, 396 v[idx[i+2]].Pos,
397 v[idx[i+0]].Pos, 397 v[idx[i+0]].Pos,
398 v[idx[i+1]].Pos, 398 v[idx[i+1]].Pos,
399 v[idx[i+2]].TCoords, 399 v[idx[i+2]].TCoords,
400 v[idx[i+0]].TCoords, 400 v[idx[i+0]].TCoords,
401 v[idx[i+1]].TCoords); 401 v[idx[i+1]].TCoords);
402 if (recalculateNormals) 402 if (recalculateNormals)
403 v[idx[i+2]].Normal=localNormal; 403 v[idx[i+2]].Normal=localNormal;
404 } 404 }
405 } 405 }
406} 406}
407} 407}
408 408
409 409
410//! Recalculates tangents for a tangent mesh buffer 410//! Recalculates tangents for a tangent mesh buffer
411void CMeshManipulator::recalculateTangents(IMeshBuffer* buffer, bool recalculateNormals, bool smooth, bool angleWeighted) const 411void CMeshManipulator::recalculateTangents(IMeshBuffer* buffer, bool recalculateNormals, bool smooth, bool angleWeighted) const
412{ 412{
413 if (buffer && (buffer->getVertexType() == video::EVT_TANGENTS)) 413 if (buffer && (buffer->getVertexType() == video::EVT_TANGENTS))
414 { 414 {
415 if (buffer->getIndexType() == video::EIT_16BIT) 415 if (buffer->getIndexType() == video::EIT_16BIT)
416 recalculateTangentsT<u16>(buffer, recalculateNormals, smooth, angleWeighted); 416 recalculateTangentsT<u16>(buffer, recalculateNormals, smooth, angleWeighted);
417 else 417 else
418 recalculateTangentsT<u32>(buffer, recalculateNormals, smooth, angleWeighted); 418 recalculateTangentsT<u32>(buffer, recalculateNormals, smooth, angleWeighted);
419 } 419 }
420} 420}
421 421
422 422
423//! Recalculates tangents for all tangent mesh buffers 423//! Recalculates tangents for all tangent mesh buffers
424void CMeshManipulator::recalculateTangents(IMesh* mesh, bool recalculateNormals, bool smooth, bool angleWeighted) const 424void CMeshManipulator::recalculateTangents(IMesh* mesh, bool recalculateNormals, bool smooth, bool angleWeighted) const
425{ 425{
426 if (!mesh) 426 if (!mesh)
427 return; 427 return;
428 428
429 const u32 meshBufferCount = mesh->getMeshBufferCount(); 429 const u32 meshBufferCount = mesh->getMeshBufferCount();
430 for (u32 b=0; b<meshBufferCount; ++b) 430 for (u32 b=0; b<meshBufferCount; ++b)
431 { 431 {
432 recalculateTangents(mesh->getMeshBuffer(b), recalculateNormals, smooth, angleWeighted); 432 recalculateTangents(mesh->getMeshBuffer(b), recalculateNormals, smooth, angleWeighted);
433 } 433 }
434} 434}
435 435
436 436
437namespace 437namespace
438{ 438{
439//! Creates a planar texture mapping on the meshbuffer 439//! Creates a planar texture mapping on the meshbuffer
440template<typename T> 440template<typename T>
441void makePlanarTextureMappingT(scene::IMeshBuffer* buffer, f32 resolution) 441void makePlanarTextureMappingT(scene::IMeshBuffer* buffer, f32 resolution)
442{ 442{
443 u32 idxcnt = buffer->getIndexCount(); 443 u32 idxcnt = buffer->getIndexCount();
444 T* idx = reinterpret_cast<T*>(buffer->getIndices()); 444 T* idx = reinterpret_cast<T*>(buffer->getIndices());
445 445
446 for (u32 i=0; i<idxcnt; i+=3) 446 for (u32 i=0; i<idxcnt; i+=3)
447 { 447 {
448 core::plane3df p(buffer->getPosition(idx[i+0]), buffer->getPosition(idx[i+1]), buffer->getPosition(idx[i+2])); 448 core::plane3df p(buffer->getPosition(idx[i+0]), buffer->getPosition(idx[i+1]), buffer->getPosition(idx[i+2]));
449 p.Normal.X = fabsf(p.Normal.X); 449 p.Normal.X = fabsf(p.Normal.X);
450 p.Normal.Y = fabsf(p.Normal.Y); 450 p.Normal.Y = fabsf(p.Normal.Y);
451 p.Normal.Z = fabsf(p.Normal.Z); 451 p.Normal.Z = fabsf(p.Normal.Z);
452 // calculate planar mapping worldspace coordinates 452 // calculate planar mapping worldspace coordinates
453 453
454 if (p.Normal.X > p.Normal.Y && p.Normal.X > p.Normal.Z) 454 if (p.Normal.X > p.Normal.Y && p.Normal.X > p.Normal.Z)
455 { 455 {
456 for (u32 o=0; o!=3; ++o) 456 for (u32 o=0; o!=3; ++o)
457 { 457 {
458 buffer->getTCoords(idx[i+o]).X = buffer->getPosition(idx[i+o]).Y * resolution; 458 buffer->getTCoords(idx[i+o]).X = buffer->getPosition(idx[i+o]).Y * resolution;
459 buffer->getTCoords(idx[i+o]).Y = buffer->getPosition(idx[i+o]).Z * resolution; 459 buffer->getTCoords(idx[i+o]).Y = buffer->getPosition(idx[i+o]).Z * resolution;
460 } 460 }
461 } 461 }
462 else 462 else
463 if (p.Normal.Y > p.Normal.X && p.Normal.Y > p.Normal.Z) 463 if (p.Normal.Y > p.Normal.X && p.Normal.Y > p.Normal.Z)
464 { 464 {
465 for (u32 o=0; o!=3; ++o) 465 for (u32 o=0; o!=3; ++o)
466 { 466 {
467 buffer->getTCoords(idx[i+o]).X = buffer->getPosition(idx[i+o]).X * resolution; 467 buffer->getTCoords(idx[i+o]).X = buffer->getPosition(idx[i+o]).X * resolution;
468 buffer->getTCoords(idx[i+o]).Y = buffer->getPosition(idx[i+o]).Z * resolution; 468 buffer->getTCoords(idx[i+o]).Y = buffer->getPosition(idx[i+o]).Z * resolution;
469 } 469 }
470 } 470 }
471 else 471 else
472 { 472 {
473 for (u32 o=0; o!=3; ++o) 473 for (u32 o=0; o!=3; ++o)
474 { 474 {
475 buffer->getTCoords(idx[i+o]).X = buffer->getPosition(idx[i+o]).X * resolution; 475 buffer->getTCoords(idx[i+o]).X = buffer->getPosition(idx[i+o]).X * resolution;
476 buffer->getTCoords(idx[i+o]).Y = buffer->getPosition(idx[i+o]).Y * resolution; 476 buffer->getTCoords(idx[i+o]).Y = buffer->getPosition(idx[i+o]).Y * resolution;
477 } 477 }
478 } 478 }
479 } 479 }
480} 480}
481} 481}
482 482
483 483
484//! Creates a planar texture mapping on the meshbuffer 484//! Creates a planar texture mapping on the meshbuffer
485void CMeshManipulator::makePlanarTextureMapping(scene::IMeshBuffer* buffer, f32 resolution) const 485void CMeshManipulator::makePlanarTextureMapping(scene::IMeshBuffer* buffer, f32 resolution) const
486{ 486{
487 if (!buffer) 487 if (!buffer)
488 return; 488 return;
489 489
490 if (buffer->getIndexType()==video::EIT_16BIT) 490 if (buffer->getIndexType()==video::EIT_16BIT)
491 makePlanarTextureMappingT<u16>(buffer, resolution); 491 makePlanarTextureMappingT<u16>(buffer, resolution);
492 else 492 else
493 makePlanarTextureMappingT<u32>(buffer, resolution); 493 makePlanarTextureMappingT<u32>(buffer, resolution);
494} 494}
495 495
496 496
497//! Creates a planar texture mapping on the mesh 497//! Creates a planar texture mapping on the mesh
498void CMeshManipulator::makePlanarTextureMapping(scene::IMesh* mesh, f32 resolution) const 498void CMeshManipulator::makePlanarTextureMapping(scene::IMesh* mesh, f32 resolution) const
499{ 499{
500 if (!mesh) 500 if (!mesh)
501 return; 501 return;
502 502
503 const u32 bcount = mesh->getMeshBufferCount(); 503 const u32 bcount = mesh->getMeshBufferCount();
504 for ( u32 b=0; b<bcount; ++b) 504 for ( u32 b=0; b<bcount; ++b)
505 { 505 {
506 makePlanarTextureMapping(mesh->getMeshBuffer(b), resolution); 506 makePlanarTextureMapping(mesh->getMeshBuffer(b), resolution);
507 } 507 }
508} 508}
509 509
510 510
511namespace 511namespace
512{ 512{
513//! Creates a planar texture mapping on the meshbuffer 513//! Creates a planar texture mapping on the meshbuffer
514template <typename T> 514template <typename T>
515void makePlanarTextureMappingT(scene::IMeshBuffer* buffer, f32 resolutionS, f32 resolutionT, u8 axis, const core::vector3df& offset) 515void makePlanarTextureMappingT(scene::IMeshBuffer* buffer, f32 resolutionS, f32 resolutionT, u8 axis, const core::vector3df& offset)
516{ 516{
517 u32 idxcnt = buffer->getIndexCount(); 517 u32 idxcnt = buffer->getIndexCount();
518 T* idx = reinterpret_cast<T*>(buffer->getIndices()); 518 T* idx = reinterpret_cast<T*>(buffer->getIndices());
519 519
520 for (u32 i=0; i<idxcnt; i+=3) 520 for (u32 i=0; i<idxcnt; i+=3)
521 { 521 {
522 // calculate planar mapping worldspace coordinates 522 // calculate planar mapping worldspace coordinates
523 if (axis==0) 523 if (axis==0)
524 { 524 {
525 for (u32 o=0; o!=3; ++o) 525 for (u32 o=0; o!=3; ++o)
526 { 526 {
527 buffer->getTCoords(idx[i+o]).X = 0.5f+(buffer->getPosition(idx[i+o]).Z + offset.Z) * resolutionS; 527 buffer->getTCoords(idx[i+o]).X = 0.5f+(buffer->getPosition(idx[i+o]).Z + offset.Z) * resolutionS;
528 buffer->getTCoords(idx[i+o]).Y = 0.5f-(buffer->getPosition(idx[i+o]).Y + offset.Y) * resolutionT; 528 buffer->getTCoords(idx[i+o]).Y = 0.5f-(buffer->getPosition(idx[i+o]).Y + offset.Y) * resolutionT;
529 } 529 }
530 } 530 }
531 else if (axis==1) 531 else if (axis==1)
532 { 532 {
533 for (u32 o=0; o!=3; ++o) 533 for (u32 o=0; o!=3; ++o)
534 { 534 {
535 buffer->getTCoords(idx[i+o]).X = 0.5f+(buffer->getPosition(idx[i+o]).X + offset.X) * resolutionS; 535 buffer->getTCoords(idx[i+o]).X = 0.5f+(buffer->getPosition(idx[i+o]).X + offset.X) * resolutionS;
536 buffer->getTCoords(idx[i+o]).Y = 1.f-(buffer->getPosition(idx[i+o]).Z + offset.Z) * resolutionT; 536 buffer->getTCoords(idx[i+o]).Y = 1.f-(buffer->getPosition(idx[i+o]).Z + offset.Z) * resolutionT;
537 } 537 }
538 } 538 }
539 else if (axis==2) 539 else if (axis==2)
540 { 540 {
541 for (u32 o=0; o!=3; ++o) 541 for (u32 o=0; o!=3; ++o)
542 { 542 {
543 buffer->getTCoords(idx[i+o]).X = 0.5f+(buffer->getPosition(idx[i+o]).X + offset.X) * resolutionS; 543 buffer->getTCoords(idx[i+o]).X = 0.5f+(buffer->getPosition(idx[i+o]).X + offset.X) * resolutionS;
544 buffer->getTCoords(idx[i+o]).Y = 0.5f-(buffer->getPosition(idx[i+o]).Y + offset.Y) * resolutionT; 544 buffer->getTCoords(idx[i+o]).Y = 0.5f-(buffer->getPosition(idx[i+o]).Y + offset.Y) * resolutionT;
545 } 545 }
546 } 546 }
547 } 547 }
548} 548}
549} 549}
550 550
551 551
552//! Creates a planar texture mapping on the meshbuffer 552//! Creates a planar texture mapping on the meshbuffer
553void CMeshManipulator::makePlanarTextureMapping(scene::IMeshBuffer* buffer, f32 resolutionS, f32 resolutionT, u8 axis, const core::vector3df& offset) const 553void CMeshManipulator::makePlanarTextureMapping(scene::IMeshBuffer* buffer, f32 resolutionS, f32 resolutionT, u8 axis, const core::vector3df& offset) const
554{ 554{
555 if (!buffer) 555 if (!buffer)
556 return; 556 return;
557 557
558 if (buffer->getIndexType()==video::EIT_16BIT) 558 if (buffer->getIndexType()==video::EIT_16BIT)
559 makePlanarTextureMappingT<u16>(buffer, resolutionS, resolutionT, axis, offset); 559 makePlanarTextureMappingT<u16>(buffer, resolutionS, resolutionT, axis, offset);
560 else 560 else
561 makePlanarTextureMappingT<u32>(buffer, resolutionS, resolutionT, axis, offset); 561 makePlanarTextureMappingT<u32>(buffer, resolutionS, resolutionT, axis, offset);
562} 562}
563 563
564 564
565//! Creates a planar texture mapping on the mesh 565//! Creates a planar texture mapping on the mesh
566void CMeshManipulator::makePlanarTextureMapping(scene::IMesh* mesh, f32 resolutionS, f32 resolutionT, u8 axis, const core::vector3df& offset) const 566void CMeshManipulator::makePlanarTextureMapping(scene::IMesh* mesh, f32 resolutionS, f32 resolutionT, u8 axis, const core::vector3df& offset) const
567{ 567{
568 if (!mesh) 568 if (!mesh)
569 return; 569 return;
570 570
571 const u32 bcount = mesh->getMeshBufferCount(); 571 const u32 bcount = mesh->getMeshBufferCount();
572 for ( u32 b=0; b<bcount; ++b) 572 for ( u32 b=0; b<bcount; ++b)
573 { 573 {
574 makePlanarTextureMapping(mesh->getMeshBuffer(b), resolutionS, resolutionT, axis, offset); 574 makePlanarTextureMapping(mesh->getMeshBuffer(b), resolutionS, resolutionT, axis, offset);
575 } 575 }
576} 576}
577 577
578 578
579//! Clones a static IMesh into a modifyable SMesh. 579//! Clones a static IMesh into a modifyable SMesh.
580// not yet 32bit 580// not yet 32bit
581SMesh* CMeshManipulator::createMeshCopy(scene::IMesh* mesh) const 581SMesh* CMeshManipulator::createMeshCopy(scene::IMesh* mesh) const
582{ 582{
583 if (!mesh) 583 if (!mesh)
584 return 0; 584 return 0;
585 585
586 SMesh* clone = new SMesh(); 586 SMesh* clone = new SMesh();
587 587
588 const u32 meshBufferCount = mesh->getMeshBufferCount(); 588 const u32 meshBufferCount = mesh->getMeshBufferCount();
589 589
590 for ( u32 b=0; b<meshBufferCount; ++b) 590 for ( u32 b=0; b<meshBufferCount; ++b)
591 { 591 {
592 const IMeshBuffer* const mb = mesh->getMeshBuffer(b); 592 const IMeshBuffer* const mb = mesh->getMeshBuffer(b);
593 switch(mb->getVertexType()) 593 switch(mb->getVertexType())
594 { 594 {
595 case video::EVT_STANDARD: 595 case video::EVT_STANDARD:
596 { 596 {
597 SMeshBuffer* buffer = new SMeshBuffer(); 597 SMeshBuffer* buffer = new SMeshBuffer();
598 buffer->Material = mb->getMaterial(); 598 buffer->Material = mb->getMaterial();
599 const u32 vcount = mb->getVertexCount(); 599 const u32 vcount = mb->getVertexCount();
600 buffer->Vertices.reallocate(vcount); 600 buffer->Vertices.reallocate(vcount);
601 video::S3DVertex* vertices = (video::S3DVertex*)mb->getVertices(); 601 video::S3DVertex* vertices = (video::S3DVertex*)mb->getVertices();
602 for (u32 i=0; i < vcount; ++i) 602 for (u32 i=0; i < vcount; ++i)
603 buffer->Vertices.push_back(vertices[i]); 603 buffer->Vertices.push_back(vertices[i]);
604 const u32 icount = mb->getIndexCount(); 604 const u32 icount = mb->getIndexCount();
605 buffer->Indices.reallocate(icount); 605 buffer->Indices.reallocate(icount);
606 const u16* indices = mb->getIndices(); 606 const u16* indices = mb->getIndices();
607 for (u32 i=0; i < icount; ++i) 607 for (u32 i=0; i < icount; ++i)
608 buffer->Indices.push_back(indices[i]); 608 buffer->Indices.push_back(indices[i]);
609 clone->addMeshBuffer(buffer); 609 clone->addMeshBuffer(buffer);
610 buffer->drop(); 610 buffer->drop();
611 } 611 }
612 break; 612 break;
613 case video::EVT_2TCOORDS: 613 case video::EVT_2TCOORDS:
614 { 614 {
615 SMeshBufferLightMap* buffer = new SMeshBufferLightMap(); 615 SMeshBufferLightMap* buffer = new SMeshBufferLightMap();
616 buffer->Material = mb->getMaterial(); 616 buffer->Material = mb->getMaterial();
617 const u32 vcount = mb->getVertexCount(); 617 const u32 vcount = mb->getVertexCount();
618 buffer->Vertices.reallocate(vcount); 618 buffer->Vertices.reallocate(vcount);
619 video::S3DVertex2TCoords* vertices = (video::S3DVertex2TCoords*)mb->getVertices(); 619 video::S3DVertex2TCoords* vertices = (video::S3DVertex2TCoords*)mb->getVertices();
620 for (u32 i=0; i < vcount; ++i) 620 for (u32 i=0; i < vcount; ++i)
621 buffer->Vertices.push_back(vertices[i]); 621 buffer->Vertices.push_back(vertices[i]);
622 const u32 icount = mb->getIndexCount(); 622 const u32 icount = mb->getIndexCount();
623 buffer->Indices.reallocate(icount); 623 buffer->Indices.reallocate(icount);
624 const u16* indices = mb->getIndices(); 624 const u16* indices = mb->getIndices();
625 for (u32 i=0; i < icount; ++i) 625 for (u32 i=0; i < icount; ++i)
626 buffer->Indices.push_back(indices[i]); 626 buffer->Indices.push_back(indices[i]);
627 clone->addMeshBuffer(buffer); 627 clone->addMeshBuffer(buffer);
628 buffer->drop(); 628 buffer->drop();
629 } 629 }
630 break; 630 break;
631 case video::EVT_TANGENTS: 631 case video::EVT_TANGENTS:
632 { 632 {
633 SMeshBufferTangents* buffer = new SMeshBufferTangents(); 633 SMeshBufferTangents* buffer = new SMeshBufferTangents();
634 buffer->Material = mb->getMaterial(); 634 buffer->Material = mb->getMaterial();
635 const u32 vcount = mb->getVertexCount(); 635 const u32 vcount = mb->getVertexCount();
636 buffer->Vertices.reallocate(vcount); 636 buffer->Vertices.reallocate(vcount);
637 video::S3DVertexTangents* vertices = (video::S3DVertexTangents*)mb->getVertices(); 637 video::S3DVertexTangents* vertices = (video::S3DVertexTangents*)mb->getVertices();
638 for (u32 i=0; i < vcount; ++i) 638 for (u32 i=0; i < vcount; ++i)
639 buffer->Vertices.push_back(vertices[i]); 639 buffer->Vertices.push_back(vertices[i]);
640 const u32 icount = mb->getIndexCount(); 640 const u32 icount = mb->getIndexCount();
641 buffer->Indices.reallocate(icount); 641 buffer->Indices.reallocate(icount);
642 const u16* indices = mb->getIndices(); 642 const u16* indices = mb->getIndices();
643 for (u32 i=0; i < icount; ++i) 643 for (u32 i=0; i < icount; ++i)
644 buffer->Indices.push_back(indices[i]); 644 buffer->Indices.push_back(indices[i]);
645 clone->addMeshBuffer(buffer); 645 clone->addMeshBuffer(buffer);
646 buffer->drop(); 646 buffer->drop();
647 } 647 }
648 break; 648 break;
649 }// end switch 649 }// end switch
650 650
651 }// end for all mesh buffers 651 }// end for all mesh buffers
652 652
653 clone->BoundingBox = mesh->getBoundingBox(); 653 clone->BoundingBox = mesh->getBoundingBox();
654 return clone; 654 return clone;
655} 655}
656 656
657 657
658//! Creates a copy of the mesh, which will only consist of unique primitives 658//! Creates a copy of the mesh, which will only consist of unique primitives
659// not yet 32bit 659// not yet 32bit
660IMesh* CMeshManipulator::createMeshUniquePrimitives(IMesh* mesh) const 660IMesh* CMeshManipulator::createMeshUniquePrimitives(IMesh* mesh) const
661{ 661{
662 if (!mesh) 662 if (!mesh)
663 return 0; 663 return 0;
664 664
665 SMesh* clone = new SMesh(); 665 SMesh* clone = new SMesh();
666 666
667 const u32 meshBufferCount = mesh->getMeshBufferCount(); 667 const u32 meshBufferCount = mesh->getMeshBufferCount();
668 668
669 for ( u32 b=0; b<meshBufferCount; ++b) 669 for ( u32 b=0; b<meshBufferCount; ++b)
670 { 670 {
671 const IMeshBuffer* const mb = mesh->getMeshBuffer(b); 671 const IMeshBuffer* const mb = mesh->getMeshBuffer(b);
672 const s32 idxCnt = mb->getIndexCount(); 672 const s32 idxCnt = mb->getIndexCount();
673 const u16* idx = mb->getIndices(); 673 const u16* idx = mb->getIndices();
674 674
675 switch(mb->getVertexType()) 675 switch(mb->getVertexType())
676 { 676 {
677 case video::EVT_STANDARD: 677 case video::EVT_STANDARD:
678 { 678 {
679 SMeshBuffer* buffer = new SMeshBuffer(); 679 SMeshBuffer* buffer = new SMeshBuffer();
680 buffer->Material = mb->getMaterial(); 680 buffer->Material = mb->getMaterial();
681 681
682 video::S3DVertex* v = 682 video::S3DVertex* v =
683 (video::S3DVertex*)mb->getVertices(); 683 (video::S3DVertex*)mb->getVertices();
684 684
685 buffer->Vertices.reallocate(idxCnt); 685 buffer->Vertices.reallocate(idxCnt);
686 buffer->Indices.reallocate(idxCnt); 686 buffer->Indices.reallocate(idxCnt);
687 for (s32 i=0; i<idxCnt; i += 3) 687 for (s32 i=0; i<idxCnt; i += 3)
688 { 688 {
689 buffer->Vertices.push_back( v[idx[i + 0 ]] ); 689 buffer->Vertices.push_back( v[idx[i + 0 ]] );
690 buffer->Vertices.push_back( v[idx[i + 1 ]] ); 690 buffer->Vertices.push_back( v[idx[i + 1 ]] );
691 buffer->Vertices.push_back( v[idx[i + 2 ]] ); 691 buffer->Vertices.push_back( v[idx[i + 2 ]] );
692 692
693 buffer->Indices.push_back( i + 0 ); 693 buffer->Indices.push_back( i + 0 );
694 buffer->Indices.push_back( i + 1 ); 694 buffer->Indices.push_back( i + 1 );
695 buffer->Indices.push_back( i + 2 ); 695 buffer->Indices.push_back( i + 2 );
696 } 696 }
697 697
698 buffer->setBoundingBox(mb->getBoundingBox()); 698 buffer->setBoundingBox(mb->getBoundingBox());
699 clone->addMeshBuffer(buffer); 699 clone->addMeshBuffer(buffer);
700 buffer->drop(); 700 buffer->drop();
701 } 701 }
702 break; 702 break;
703 case video::EVT_2TCOORDS: 703 case video::EVT_2TCOORDS:
704 { 704 {
705 SMeshBufferLightMap* buffer = new SMeshBufferLightMap(); 705 SMeshBufferLightMap* buffer = new SMeshBufferLightMap();
706 buffer->Material = mb->getMaterial(); 706 buffer->Material = mb->getMaterial();
707 707
708 video::S3DVertex2TCoords* v = 708 video::S3DVertex2TCoords* v =
709 (video::S3DVertex2TCoords*)mb->getVertices(); 709 (video::S3DVertex2TCoords*)mb->getVertices();
710 710
711 buffer->Vertices.reallocate(idxCnt); 711 buffer->Vertices.reallocate(idxCnt);
712 buffer->Indices.reallocate(idxCnt); 712 buffer->Indices.reallocate(idxCnt);
713 for (s32 i=0; i<idxCnt; i += 3) 713 for (s32 i=0; i<idxCnt; i += 3)
714 { 714 {
715 buffer->Vertices.push_back( v[idx[i + 0 ]] ); 715 buffer->Vertices.push_back( v[idx[i + 0 ]] );
716 buffer->Vertices.push_back( v[idx[i + 1 ]] ); 716 buffer->Vertices.push_back( v[idx[i + 1 ]] );
717 buffer->Vertices.push_back( v[idx[i + 2 ]] ); 717 buffer->Vertices.push_back( v[idx[i + 2 ]] );
718 718
719 buffer->Indices.push_back( i + 0 ); 719 buffer->Indices.push_back( i + 0 );
720 buffer->Indices.push_back( i + 1 ); 720 buffer->Indices.push_back( i + 1 );
721 buffer->Indices.push_back( i + 2 ); 721 buffer->Indices.push_back( i + 2 );
722 } 722 }
723 buffer->setBoundingBox(mb->getBoundingBox()); 723 buffer->setBoundingBox(mb->getBoundingBox());
724 clone->addMeshBuffer(buffer); 724 clone->addMeshBuffer(buffer);
725 buffer->drop(); 725 buffer->drop();
726 } 726 }
727 break; 727 break;
728 case video::EVT_TANGENTS: 728 case video::EVT_TANGENTS:
729 { 729 {
730 SMeshBufferTangents* buffer = new SMeshBufferTangents(); 730 SMeshBufferTangents* buffer = new SMeshBufferTangents();
731 buffer->Material = mb->getMaterial(); 731 buffer->Material = mb->getMaterial();
732 732
733 video::S3DVertexTangents* v = 733 video::S3DVertexTangents* v =
734 (video::S3DVertexTangents*)mb->getVertices(); 734 (video::S3DVertexTangents*)mb->getVertices();
735 735
736 buffer->Vertices.reallocate(idxCnt); 736 buffer->Vertices.reallocate(idxCnt);
737 buffer->Indices.reallocate(idxCnt); 737 buffer->Indices.reallocate(idxCnt);
738 for (s32 i=0; i<idxCnt; i += 3) 738 for (s32 i=0; i<idxCnt; i += 3)
739 { 739 {
740 buffer->Vertices.push_back( v[idx[i + 0 ]] ); 740 buffer->Vertices.push_back( v[idx[i + 0 ]] );
741 buffer->Vertices.push_back( v[idx[i + 1 ]] ); 741 buffer->Vertices.push_back( v[idx[i + 1 ]] );
742 buffer->Vertices.push_back( v[idx[i + 2 ]] ); 742 buffer->Vertices.push_back( v[idx[i + 2 ]] );
743 743
744 buffer->Indices.push_back( i + 0 ); 744 buffer->Indices.push_back( i + 0 );
745 buffer->Indices.push_back( i + 1 ); 745 buffer->Indices.push_back( i + 1 );
746 buffer->Indices.push_back( i + 2 ); 746 buffer->Indices.push_back( i + 2 );
747 } 747 }
748 748
749 buffer->setBoundingBox(mb->getBoundingBox()); 749 buffer->setBoundingBox(mb->getBoundingBox());
750 clone->addMeshBuffer(buffer); 750 clone->addMeshBuffer(buffer);
751 buffer->drop(); 751 buffer->drop();
752 } 752 }
753 break; 753 break;
754 }// end switch 754 }// end switch
755 755
756 }// end for all mesh buffers 756 }// end for all mesh buffers
757 757
758 clone->BoundingBox = mesh->getBoundingBox(); 758 clone->BoundingBox = mesh->getBoundingBox();
759 return clone; 759 return clone;
760} 760}
761 761
762 762
763//! Creates a copy of a mesh, which will have identical vertices welded together 763//! Creates a copy of a mesh, which will have identical vertices welded together
764// not yet 32bit 764// not yet 32bit
765IMesh* CMeshManipulator::createMeshWelded(IMesh *mesh, f32 tolerance) const 765IMesh* CMeshManipulator::createMeshWelded(IMesh *mesh, f32 tolerance) const
766{ 766{
767 SMesh* clone = new SMesh(); 767 SMesh* clone = new SMesh();
768 clone->BoundingBox = mesh->getBoundingBox(); 768 clone->BoundingBox = mesh->getBoundingBox();
769 769
770 core::array<u16> redirects; 770 core::array<u16> redirects;
771 771
772 for (u32 b=0; b<mesh->getMeshBufferCount(); ++b) 772 for (u32 b=0; b<mesh->getMeshBufferCount(); ++b)
773 { 773 {
774 const IMeshBuffer* const mb = mesh->getMeshBuffer(b); 774 const IMeshBuffer* const mb = mesh->getMeshBuffer(b);
775 // reset redirect list 775 // reset redirect list
776 redirects.set_used(mb->getVertexCount()); 776 redirects.set_used(mb->getVertexCount());
777 777
778 const u16* indices = 0; 778 const u16* indices = 0;
779 u32 indexCount = 0; 779 u32 indexCount = 0;
780 core::array<u16>* outIdx = 0; 780 core::array<u16>* outIdx = 0;
781 781
782 switch(mb->getVertexType()) 782 switch(mb->getVertexType())
783 { 783 {
784 case video::EVT_STANDARD: 784 case video::EVT_STANDARD:
785 { 785 {
786 SMeshBuffer* buffer = new SMeshBuffer(); 786 SMeshBuffer* buffer = new SMeshBuffer();
787 buffer->BoundingBox = mb->getBoundingBox(); 787 buffer->BoundingBox = mb->getBoundingBox();
788 buffer->Material = mb->getMaterial(); 788 buffer->Material = mb->getMaterial();
789 clone->addMeshBuffer(buffer); 789 clone->addMeshBuffer(buffer);
790 buffer->drop(); 790 buffer->drop();
791 791
792 video::S3DVertex* v = 792 video::S3DVertex* v =
793 (video::S3DVertex*)mb->getVertices(); 793 (video::S3DVertex*)mb->getVertices();
794 794
795 u32 vertexCount = mb->getVertexCount(); 795 u32 vertexCount = mb->getVertexCount();
796 796
797 indices = mb->getIndices(); 797 indices = mb->getIndices();
798 indexCount = mb->getIndexCount(); 798 indexCount = mb->getIndexCount();
799 outIdx = &buffer->Indices; 799 outIdx = &buffer->Indices;
800 800
801 buffer->Vertices.reallocate(vertexCount); 801 buffer->Vertices.reallocate(vertexCount);
802 802
803 for (u32 i=0; i < vertexCount; ++i) 803 for (u32 i=0; i < vertexCount; ++i)
804 { 804 {
805 bool found = false; 805 bool found = false;
806 for (u32 j=0; j < i; ++j) 806 for (u32 j=0; j < i; ++j)
807 { 807 {
808 if ( v[i].Pos.equals( v[j].Pos, tolerance) && 808 if ( v[i].Pos.equals( v[j].Pos, tolerance) &&
809 v[i].Normal.equals( v[j].Normal, tolerance) && 809 v[i].Normal.equals( v[j].Normal, tolerance) &&
810 v[i].TCoords.equals( v[j].TCoords ) && 810 v[i].TCoords.equals( v[j].TCoords ) &&
811 (v[i].Color == v[j].Color) ) 811 (v[i].Color == v[j].Color) )
812 { 812 {
813 redirects[i] = redirects[j]; 813 redirects[i] = redirects[j];
814 found = true; 814 found = true;
815 break; 815 break;
816 } 816 }
817 } 817 }
818 if (!found) 818 if (!found)
819 { 819 {
820 redirects[i] = buffer->Vertices.size(); 820 redirects[i] = buffer->Vertices.size();
821 buffer->Vertices.push_back(v[i]); 821 buffer->Vertices.push_back(v[i]);
822 } 822 }
823 } 823 }
824 824
825 break; 825 break;
826 } 826 }
827 case video::EVT_2TCOORDS: 827 case video::EVT_2TCOORDS:
828 { 828 {
829 SMeshBufferLightMap* buffer = new SMeshBufferLightMap(); 829 SMeshBufferLightMap* buffer = new SMeshBufferLightMap();
830 buffer->BoundingBox = mb->getBoundingBox(); 830 buffer->BoundingBox = mb->getBoundingBox();
831 buffer->Material = mb->getMaterial(); 831 buffer->Material = mb->getMaterial();
832 clone->addMeshBuffer(buffer); 832 clone->addMeshBuffer(buffer);
833 buffer->drop(); 833 buffer->drop();
834 834
835 video::S3DVertex2TCoords* v = 835 video::S3DVertex2TCoords* v =
836 (video::S3DVertex2TCoords*)mb->getVertices(); 836 (video::S3DVertex2TCoords*)mb->getVertices();
837 837
838 u32 vertexCount = mb->getVertexCount(); 838 u32 vertexCount = mb->getVertexCount();
839 839
840 indices = mb->getIndices(); 840 indices = mb->getIndices();
841 indexCount = mb->getIndexCount(); 841 indexCount = mb->getIndexCount();
842 outIdx = &buffer->Indices; 842 outIdx = &buffer->Indices;
843 843
844 buffer->Vertices.reallocate(vertexCount); 844 buffer->Vertices.reallocate(vertexCount);
845 845
846 for (u32 i=0; i < vertexCount; ++i) 846 for (u32 i=0; i < vertexCount; ++i)
847 { 847 {
848 bool found = false; 848 bool found = false;
849 for (u32 j=0; j < i; ++j) 849 for (u32 j=0; j < i; ++j)
850 { 850 {
851 if ( v[i].Pos.equals( v[j].Pos, tolerance) && 851 if ( v[i].Pos.equals( v[j].Pos, tolerance) &&
852 v[i].Normal.equals( v[j].Normal, tolerance) && 852 v[i].Normal.equals( v[j].Normal, tolerance) &&
853 v[i].TCoords.equals( v[j].TCoords ) && 853 v[i].TCoords.equals( v[j].TCoords ) &&
854 v[i].TCoords2.equals( v[j].TCoords2 ) && 854 v[i].TCoords2.equals( v[j].TCoords2 ) &&
855 (v[i].Color == v[j].Color) ) 855 (v[i].Color == v[j].Color) )
856 { 856 {
857 redirects[i] = redirects[j]; 857 redirects[i] = redirects[j];
858 found = true; 858 found = true;
859 break; 859 break;
860 } 860 }
861 } 861 }
862 if (!found) 862 if (!found)
863 { 863 {
864 redirects[i] = buffer->Vertices.size(); 864 redirects[i] = buffer->Vertices.size();
865 buffer->Vertices.push_back(v[i]); 865 buffer->Vertices.push_back(v[i]);
866 } 866 }
867 } 867 }
868 break; 868 break;
869 } 869 }
870 case video::EVT_TANGENTS: 870 case video::EVT_TANGENTS:
871 { 871 {
872 SMeshBufferTangents* buffer = new SMeshBufferTangents(); 872 SMeshBufferTangents* buffer = new SMeshBufferTangents();
873 buffer->BoundingBox = mb->getBoundingBox(); 873 buffer->BoundingBox = mb->getBoundingBox();
874 buffer->Material = mb->getMaterial(); 874 buffer->Material = mb->getMaterial();
875 clone->addMeshBuffer(buffer); 875 clone->addMeshBuffer(buffer);
876 buffer->drop(); 876 buffer->drop();
877 877
878 video::S3DVertexTangents* v = 878 video::S3DVertexTangents* v =
879 (video::S3DVertexTangents*)mb->getVertices(); 879 (video::S3DVertexTangents*)mb->getVertices();
880 880
881 u32 vertexCount = mb->getVertexCount(); 881 u32 vertexCount = mb->getVertexCount();
882 882
883 indices = mb->getIndices(); 883 indices = mb->getIndices();
884 indexCount = mb->getIndexCount(); 884 indexCount = mb->getIndexCount();
885 outIdx = &buffer->Indices; 885 outIdx = &buffer->Indices;
886 886
887 buffer->Vertices.reallocate(vertexCount); 887 buffer->Vertices.reallocate(vertexCount);
888 888
889 for (u32 i=0; i < vertexCount; ++i) 889 for (u32 i=0; i < vertexCount; ++i)
890 { 890 {
891 bool found = false; 891 bool found = false;
892 for (u32 j=0; j < i; ++j) 892 for (u32 j=0; j < i; ++j)
893 { 893 {
894 if ( v[i].Pos.equals( v[j].Pos, tolerance) && 894 if ( v[i].Pos.equals( v[j].Pos, tolerance) &&
895 v[i].Normal.equals( v[j].Normal, tolerance) && 895 v[i].Normal.equals( v[j].Normal, tolerance) &&
896 v[i].TCoords.equals( v[j].TCoords ) && 896 v[i].TCoords.equals( v[j].TCoords ) &&
897 v[i].Tangent.equals( v[j].Tangent, tolerance ) && 897 v[i].Tangent.equals( v[j].Tangent, tolerance ) &&
898 v[i].Binormal.equals( v[j].Binormal, tolerance ) && 898 v[i].Binormal.equals( v[j].Binormal, tolerance ) &&
899 (v[i].Color == v[j].Color) ) 899 (v[i].Color == v[j].Color) )
900 { 900 {
901 redirects[i] = redirects[j]; 901 redirects[i] = redirects[j];
902 found = true; 902 found = true;
903 break; 903 break;
904 } 904 }
905 } 905 }
906 if (!found) 906 if (!found)
907 { 907 {
908 redirects[i] = buffer->Vertices.size(); 908 redirects[i] = buffer->Vertices.size();
909 buffer->Vertices.push_back(v[i]); 909 buffer->Vertices.push_back(v[i]);
910 } 910 }
911 } 911 }
912 break; 912 break;
913 } 913 }
914 default: 914 default:
915 os::Printer::log("Cannot create welded mesh, vertex type unsupported", ELL_ERROR); 915 os::Printer::log("Cannot create welded mesh, vertex type unsupported", ELL_ERROR);
916 break; 916 break;
917 } 917 }
918 918
919 // write the buffer's index list 919 // write the buffer's index list
920 core::array<u16> &Indices = *outIdx; 920 core::array<u16> &Indices = *outIdx;
921 921
922 Indices.set_used(indexCount); 922 Indices.set_used(indexCount);
923 for (u32 i=0; i<indexCount; ++i) 923 for (u32 i=0; i<indexCount; ++i)
924 { 924 {
925 Indices[i] = redirects[ indices[i] ]; 925 Indices[i] = redirects[ indices[i] ];
926 } 926 }
927 } 927 }
928 return clone; 928 return clone;
929} 929}
930 930
931 931
932//! Creates a copy of the mesh, which will only consist of S3DVertexTangents vertices. 932//! Creates a copy of the mesh, which will only consist of S3DVertexTangents vertices.
933// not yet 32bit 933// not yet 32bit
934IMesh* CMeshManipulator::createMeshWithTangents(IMesh* mesh, bool recalculateNormals, bool smooth, bool angleWeighted, bool calculateTangents) const 934IMesh* CMeshManipulator::createMeshWithTangents(IMesh* mesh, bool recalculateNormals, bool smooth, bool angleWeighted, bool calculateTangents) const
935{ 935{
936 if (!mesh) 936 if (!mesh)
937 return 0; 937 return 0;
938 938
939 // copy mesh and fill data into SMeshBufferTangents 939 // copy mesh and fill data into SMeshBufferTangents
940 940
941 SMesh* clone = new SMesh(); 941 SMesh* clone = new SMesh();
942 const u32 meshBufferCount = mesh->getMeshBufferCount(); 942 const u32 meshBufferCount = mesh->getMeshBufferCount();
943 943
944 for (u32 b=0; b<meshBufferCount; ++b) 944 for (u32 b=0; b<meshBufferCount; ++b)
945 { 945 {
946 const IMeshBuffer* const original = mesh->getMeshBuffer(b); 946 const IMeshBuffer* const original = mesh->getMeshBuffer(b);
947 const u32 idxCnt = original->getIndexCount(); 947 const u32 idxCnt = original->getIndexCount();
948 const u16* idx = original->getIndices(); 948 const u16* idx = original->getIndices();
949 949
950 SMeshBufferTangents* buffer = new SMeshBufferTangents(); 950 SMeshBufferTangents* buffer = new SMeshBufferTangents();
951 951
952 buffer->Material = original->getMaterial(); 952 buffer->Material = original->getMaterial();
953 buffer->Vertices.reallocate(idxCnt); 953 buffer->Vertices.reallocate(idxCnt);
954 buffer->Indices.reallocate(idxCnt); 954 buffer->Indices.reallocate(idxCnt);
955 955
956 core::map<video::S3DVertexTangents, int> vertMap; 956 core::map<video::S3DVertexTangents, int> vertMap;
957 int vertLocation; 957 int vertLocation;
958 958
959 // copy vertices 959 // copy vertices
960 960
961 const video::E_VERTEX_TYPE vType = original->getVertexType(); 961 const video::E_VERTEX_TYPE vType = original->getVertexType();
962 video::S3DVertexTangents vNew; 962 video::S3DVertexTangents vNew;
963 for (u32 i=0; i<idxCnt; ++i) 963 for (u32 i=0; i<idxCnt; ++i)
964 { 964 {
965 switch(vType) 965 switch(vType)
966 { 966 {
967 case video::EVT_STANDARD: 967 case video::EVT_STANDARD:
968 { 968 {
969 const video::S3DVertex* v = 969 const video::S3DVertex* v =
970 (const video::S3DVertex*)original->getVertices(); 970 (const video::S3DVertex*)original->getVertices();
971 vNew = video::S3DVertexTangents( 971 vNew = video::S3DVertexTangents(
972 v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords); 972 v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords);
973 } 973 }
974 break; 974 break;
975 case video::EVT_2TCOORDS: 975 case video::EVT_2TCOORDS:
976 { 976 {
977 const video::S3DVertex2TCoords* v = 977 const video::S3DVertex2TCoords* v =
978 (const video::S3DVertex2TCoords*)original->getVertices(); 978 (const video::S3DVertex2TCoords*)original->getVertices();
979 vNew = video::S3DVertexTangents( 979 vNew = video::S3DVertexTangents(
980 v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords); 980 v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords);
981 } 981 }
982 break; 982 break;
983 case video::EVT_TANGENTS: 983 case video::EVT_TANGENTS:
984 { 984 {
985 const video::S3DVertexTangents* v = 985 const video::S3DVertexTangents* v =
986 (const video::S3DVertexTangents*)original->getVertices(); 986 (const video::S3DVertexTangents*)original->getVertices();
987 vNew = v[idx[i]]; 987 vNew = v[idx[i]];
988 } 988 }
989 break; 989 break;
990 } 990 }
991 core::map<video::S3DVertexTangents, int>::Node* n = vertMap.find(vNew); 991 core::map<video::S3DVertexTangents, int>::Node* n = vertMap.find(vNew);
992 if (n) 992 if (n)
993 { 993 {
994 vertLocation = n->getValue(); 994 vertLocation = n->getValue();
995 } 995 }
996 else 996 else
997 { 997 {
998 vertLocation = buffer->Vertices.size(); 998 vertLocation = buffer->Vertices.size();
999 buffer->Vertices.push_back(vNew); 999 buffer->Vertices.push_back(vNew);
1000 vertMap.insert(vNew, vertLocation); 1000 vertMap.insert(vNew, vertLocation);
1001 } 1001 }
1002 1002
1003 // create new indices 1003 // create new indices
1004 buffer->Indices.push_back(vertLocation); 1004 buffer->Indices.push_back(vertLocation);
1005 } 1005 }
1006 buffer->recalculateBoundingBox(); 1006 buffer->recalculateBoundingBox();
1007 1007
1008 // add new buffer 1008 // add new buffer
1009 clone->addMeshBuffer(buffer); 1009 clone->addMeshBuffer(buffer);
1010 buffer->drop(); 1010 buffer->drop();
1011 } 1011 }
1012 1012
1013 clone->recalculateBoundingBox(); 1013 clone->recalculateBoundingBox();
1014 if (calculateTangents) 1014 if (calculateTangents)
1015 recalculateTangents(clone, recalculateNormals, smooth, angleWeighted); 1015 recalculateTangents(clone, recalculateNormals, smooth, angleWeighted);
1016 1016
1017 return clone; 1017 return clone;
1018} 1018}
1019 1019
1020 1020
1021//! Creates a copy of the mesh, which will only consist of S3DVertex2TCoords vertices. 1021//! Creates a copy of the mesh, which will only consist of S3DVertex2TCoords vertices.
1022// not yet 32bit 1022// not yet 32bit
1023IMesh* CMeshManipulator::createMeshWith2TCoords(IMesh* mesh) const 1023IMesh* CMeshManipulator::createMeshWith2TCoords(IMesh* mesh) const
1024{ 1024{
1025 if (!mesh) 1025 if (!mesh)
1026 return 0; 1026 return 0;
1027 1027
1028 // copy mesh and fill data into SMeshBufferLightMap 1028 // copy mesh and fill data into SMeshBufferLightMap
1029 1029
1030 SMesh* clone = new SMesh(); 1030 SMesh* clone = new SMesh();
1031 const u32 meshBufferCount = mesh->getMeshBufferCount(); 1031 const u32 meshBufferCount = mesh->getMeshBufferCount();
1032 1032
1033 for (u32 b=0; b<meshBufferCount; ++b) 1033 for (u32 b=0; b<meshBufferCount; ++b)
1034 { 1034 {
1035 const IMeshBuffer* const original = mesh->getMeshBuffer(b); 1035 const IMeshBuffer* const original = mesh->getMeshBuffer(b);
1036 const u32 idxCnt = original->getIndexCount(); 1036 const u32 idxCnt = original->getIndexCount();
1037 const u16* idx = original->getIndices(); 1037 const u16* idx = original->getIndices();
1038 1038
1039 SMeshBufferLightMap* buffer = new SMeshBufferLightMap(); 1039 SMeshBufferLightMap* buffer = new SMeshBufferLightMap();
1040 buffer->Material = original->getMaterial(); 1040 buffer->Material = original->getMaterial();
1041 buffer->Vertices.reallocate(idxCnt); 1041 buffer->Vertices.reallocate(idxCnt);
1042 buffer->Indices.reallocate(idxCnt); 1042 buffer->Indices.reallocate(idxCnt);
1043 1043
1044 core::map<video::S3DVertex2TCoords, int> vertMap; 1044 core::map<video::S3DVertex2TCoords, int> vertMap;
1045 int vertLocation; 1045 int vertLocation;
1046 1046
1047 // copy vertices 1047 // copy vertices
1048 1048
1049 const video::E_VERTEX_TYPE vType = original->getVertexType(); 1049 const video::E_VERTEX_TYPE vType = original->getVertexType();
1050 video::S3DVertex2TCoords vNew; 1050 video::S3DVertex2TCoords vNew;
1051 for (u32 i=0; i<idxCnt; ++i) 1051 for (u32 i=0; i<idxCnt; ++i)
1052 { 1052 {
1053 switch(vType) 1053 switch(vType)
1054 { 1054 {
1055 case video::EVT_STANDARD: 1055 case video::EVT_STANDARD:
1056 { 1056 {
1057 const video::S3DVertex* v = 1057 const video::S3DVertex* v =
1058 (const video::S3DVertex*)original->getVertices(); 1058 (const video::S3DVertex*)original->getVertices();
1059 vNew = video::S3DVertex2TCoords( 1059 vNew = video::S3DVertex2TCoords(
1060 v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords, v[idx[i]].TCoords); 1060 v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords, v[idx[i]].TCoords);
1061 } 1061 }
1062 break; 1062 break;
1063 case video::EVT_2TCOORDS: 1063 case video::EVT_2TCOORDS:
1064 { 1064 {
1065 const video::S3DVertex2TCoords* v = 1065 const video::S3DVertex2TCoords* v =
1066 (const video::S3DVertex2TCoords*)original->getVertices(); 1066 (const video::S3DVertex2TCoords*)original->getVertices();
1067 vNew = v[idx[i]]; 1067 vNew = v[idx[i]];
1068 } 1068 }
1069 break; 1069 break;
1070 case video::EVT_TANGENTS: 1070 case video::EVT_TANGENTS:
1071 { 1071 {
1072 const video::S3DVertexTangents* v = 1072 const video::S3DVertexTangents* v =
1073 (const video::S3DVertexTangents*)original->getVertices(); 1073 (const video::S3DVertexTangents*)original->getVertices();
1074 vNew = video::S3DVertex2TCoords( 1074 vNew = video::S3DVertex2TCoords(
1075 v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords, v[idx[i]].TCoords); 1075 v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords, v[idx[i]].TCoords);
1076 } 1076 }
1077 break; 1077 break;
1078 } 1078 }
1079 core::map<video::S3DVertex2TCoords, int>::Node* n = vertMap.find(vNew); 1079 core::map<video::S3DVertex2TCoords, int>::Node* n = vertMap.find(vNew);
1080 if (n) 1080 if (n)
1081 { 1081 {
1082 vertLocation = n->getValue(); 1082 vertLocation = n->getValue();
1083 } 1083 }
1084 else 1084 else
1085 { 1085 {
1086 vertLocation = buffer->Vertices.size(); 1086 vertLocation = buffer->Vertices.size();
1087 buffer->Vertices.push_back(vNew); 1087 buffer->Vertices.push_back(vNew);
1088 vertMap.insert(vNew, vertLocation); 1088 vertMap.insert(vNew, vertLocation);
1089 } 1089 }
1090 1090
1091 // create new indices 1091 // create new indices
1092 buffer->Indices.push_back(vertLocation); 1092 buffer->Indices.push_back(vertLocation);
1093 } 1093 }
1094 buffer->recalculateBoundingBox(); 1094 buffer->recalculateBoundingBox();
1095 1095
1096 // add new buffer 1096 // add new buffer
1097 clone->addMeshBuffer(buffer); 1097 clone->addMeshBuffer(buffer);
1098 buffer->drop(); 1098 buffer->drop();
1099 } 1099 }
1100 1100
1101 clone->recalculateBoundingBox(); 1101 clone->recalculateBoundingBox();
1102 return clone; 1102 return clone;
1103} 1103}
1104 1104
1105 1105
1106//! Creates a copy of the mesh, which will only consist of S3DVertex vertices. 1106//! Creates a copy of the mesh, which will only consist of S3DVertex vertices.
1107// not yet 32bit 1107// not yet 32bit
1108IMesh* CMeshManipulator::createMeshWith1TCoords(IMesh* mesh) const 1108IMesh* CMeshManipulator::createMeshWith1TCoords(IMesh* mesh) const
1109{ 1109{
1110 if (!mesh) 1110 if (!mesh)
1111 return 0; 1111 return 0;
1112 1112
1113 // copy mesh and fill data into SMeshBuffer 1113 // copy mesh and fill data into SMeshBuffer
1114 SMesh* clone = new SMesh(); 1114 SMesh* clone = new SMesh();
1115 const u32 meshBufferCount = mesh->getMeshBufferCount(); 1115 const u32 meshBufferCount = mesh->getMeshBufferCount();
1116 1116
1117 for (u32 b=0; b<meshBufferCount; ++b) 1117 for (u32 b=0; b<meshBufferCount; ++b)
1118 { 1118 {
1119 IMeshBuffer* original = mesh->getMeshBuffer(b); 1119 IMeshBuffer* original = mesh->getMeshBuffer(b);
1120 const u32 idxCnt = original->getIndexCount(); 1120 const u32 idxCnt = original->getIndexCount();
1121 const u16* idx = original->getIndices(); 1121 const u16* idx = original->getIndices();
1122 1122
1123 SMeshBuffer* buffer = new SMeshBuffer(); 1123 SMeshBuffer* buffer = new SMeshBuffer();
1124 buffer->Material = original->getMaterial(); 1124 buffer->Material = original->getMaterial();
1125 buffer->Vertices.reallocate(idxCnt); 1125 buffer->Vertices.reallocate(idxCnt);
1126 buffer->Indices.reallocate(idxCnt); 1126 buffer->Indices.reallocate(idxCnt);
1127 1127
1128 core::map<video::S3DVertex, int> vertMap; 1128 core::map<video::S3DVertex, int> vertMap;
1129 int vertLocation; 1129 int vertLocation;
1130 1130
1131 // copy vertices 1131 // copy vertices
1132 const video::E_VERTEX_TYPE vType = original->getVertexType(); 1132 const video::E_VERTEX_TYPE vType = original->getVertexType();
1133 video::S3DVertex vNew; 1133 video::S3DVertex vNew;
1134 for (u32 i=0; i<idxCnt; ++i) 1134 for (u32 i=0; i<idxCnt; ++i)
1135 { 1135 {
1136 switch(vType) 1136 switch(vType)
1137 { 1137 {
1138 case video::EVT_STANDARD: 1138 case video::EVT_STANDARD:
1139 { 1139 {
1140 video::S3DVertex* v = 1140 video::S3DVertex* v =
1141 (video::S3DVertex*)original->getVertices(); 1141 (video::S3DVertex*)original->getVertices();
1142 vNew = v[idx[i]]; 1142 vNew = v[idx[i]];
1143 } 1143 }
1144 break; 1144 break;
1145 case video::EVT_2TCOORDS: 1145 case video::EVT_2TCOORDS:
1146 { 1146 {
1147 video::S3DVertex2TCoords* v = 1147 video::S3DVertex2TCoords* v =
1148 (video::S3DVertex2TCoords*)original->getVertices(); 1148 (video::S3DVertex2TCoords*)original->getVertices();
1149 vNew = video::S3DVertex( 1149 vNew = video::S3DVertex(
1150 v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords); 1150 v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords);
1151 } 1151 }
1152 break; 1152 break;
1153 case video::EVT_TANGENTS: 1153 case video::EVT_TANGENTS:
1154 { 1154 {
1155 video::S3DVertexTangents* v = 1155 video::S3DVertexTangents* v =
1156 (video::S3DVertexTangents*)original->getVertices(); 1156 (video::S3DVertexTangents*)original->getVertices();
1157 vNew = video::S3DVertex( 1157 vNew = video::S3DVertex(
1158 v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords); 1158 v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords);
1159 } 1159 }
1160 break; 1160 break;
1161 } 1161 }
1162 core::map<video::S3DVertex, int>::Node* n = vertMap.find(vNew); 1162 core::map<video::S3DVertex, int>::Node* n = vertMap.find(vNew);
1163 if (n) 1163 if (n)
1164 { 1164 {
1165 vertLocation = n->getValue(); 1165 vertLocation = n->getValue();
1166 } 1166 }
1167 else 1167 else
1168 { 1168 {
1169 vertLocation = buffer->Vertices.size(); 1169 vertLocation = buffer->Vertices.size();
1170 buffer->Vertices.push_back(vNew); 1170 buffer->Vertices.push_back(vNew);
1171 vertMap.insert(vNew, vertLocation); 1171 vertMap.insert(vNew, vertLocation);
1172 } 1172 }
1173 1173
1174 // create new indices 1174 // create new indices
1175 buffer->Indices.push_back(vertLocation); 1175 buffer->Indices.push_back(vertLocation);
1176 } 1176 }
1177 buffer->recalculateBoundingBox(); 1177 buffer->recalculateBoundingBox();
1178 // add new buffer 1178 // add new buffer
1179 clone->addMeshBuffer(buffer); 1179 clone->addMeshBuffer(buffer);
1180 buffer->drop(); 1180 buffer->drop();
1181 } 1181 }
1182 1182
1183 clone->recalculateBoundingBox(); 1183 clone->recalculateBoundingBox();
1184 return clone; 1184 return clone;
1185} 1185}
1186 1186
1187 1187
1188//! Returns amount of polygons in mesh. 1188//! Returns amount of polygons in mesh.
1189s32 CMeshManipulator::getPolyCount(scene::IMesh* mesh) const 1189s32 CMeshManipulator::getPolyCount(scene::IMesh* mesh) const
1190{ 1190{
1191 if (!mesh) 1191 if (!mesh)
1192 return 0; 1192 return 0;
1193 1193
1194 s32 trianglecount = 0; 1194 s32 trianglecount = 0;
1195 1195
1196 for (u32 g=0; g<mesh->getMeshBufferCount(); ++g) 1196 for (u32 g=0; g<mesh->getMeshBufferCount(); ++g)
1197 trianglecount += mesh->getMeshBuffer(g)->getIndexCount() / 3; 1197 trianglecount += mesh->getMeshBuffer(g)->getIndexCount() / 3;
1198 1198
1199 return trianglecount; 1199 return trianglecount;
1200} 1200}
1201 1201
1202 1202
1203//! Returns amount of polygons in mesh. 1203//! Returns amount of polygons in mesh.
1204s32 CMeshManipulator::getPolyCount(scene::IAnimatedMesh* mesh) const 1204s32 CMeshManipulator::getPolyCount(scene::IAnimatedMesh* mesh) const
1205{ 1205{
1206 if (mesh && mesh->getFrameCount() != 0) 1206 if (mesh && mesh->getFrameCount() != 0)
1207 return getPolyCount(mesh->getMesh(0)); 1207 return getPolyCount(mesh->getMesh(0));
1208 1208
1209 return 0; 1209 return 0;
1210} 1210}
1211 1211
1212 1212
1213//! create a new AnimatedMesh and adds the mesh to it 1213//! create a new AnimatedMesh and adds the mesh to it
1214IAnimatedMesh * CMeshManipulator::createAnimatedMesh(scene::IMesh* mesh, scene::E_ANIMATED_MESH_TYPE type) const 1214IAnimatedMesh * CMeshManipulator::createAnimatedMesh(scene::IMesh* mesh, scene::E_ANIMATED_MESH_TYPE type) const
1215{ 1215{
1216 return new SAnimatedMesh(mesh, type); 1216 return new SAnimatedMesh(mesh, type);
1217} 1217}
1218 1218
1219namespace 1219namespace
1220{ 1220{
1221 1221
1222struct vcache 1222struct vcache
1223{ 1223{
1224 core::array<u32> tris; 1224 core::array<u32> tris;
1225 float score; 1225 float score;
1226 s16 cachepos; 1226 s16 cachepos;
1227 u16 NumActiveTris; 1227 u16 NumActiveTris;
1228}; 1228};
1229 1229
1230struct tcache 1230struct tcache
1231{ 1231{
1232 u16 ind[3]; 1232 u16 ind[3];
1233 float score; 1233 float score;
1234 bool drawn; 1234 bool drawn;
1235}; 1235};
1236 1236
1237const u16 cachesize = 32; 1237const u16 cachesize = 32;
1238 1238
1239float FindVertexScore(vcache *v) 1239float FindVertexScore(vcache *v)
1240{ 1240{
1241 const float CacheDecayPower = 1.5f; 1241 const float CacheDecayPower = 1.5f;
1242 const float LastTriScore = 0.75f; 1242 const float LastTriScore = 0.75f;
1243 const float ValenceBoostScale = 2.0f; 1243 const float ValenceBoostScale = 2.0f;
1244 const float ValenceBoostPower = 0.5f; 1244 const float ValenceBoostPower = 0.5f;
1245 const float MaxSizeVertexCache = 32.0f; 1245 const float MaxSizeVertexCache = 32.0f;
1246 1246
1247 if (v->NumActiveTris == 0) 1247 if (v->NumActiveTris == 0)
1248 { 1248 {
1249 // No tri needs this vertex! 1249 // No tri needs this vertex!
1250 return -1.0f; 1250 return -1.0f;
1251 } 1251 }
1252 1252
1253 float Score = 0.0f; 1253 float Score = 0.0f;
1254 int CachePosition = v->cachepos; 1254 int CachePosition = v->cachepos;
1255 if (CachePosition < 0) 1255 if (CachePosition < 0)
1256 { 1256 {
1257 // Vertex is not in FIFO cache - no score. 1257 // Vertex is not in FIFO cache - no score.
1258 } 1258 }
1259 else 1259 else
1260 { 1260 {
1261 if (CachePosition < 3) 1261 if (CachePosition < 3)
1262 { 1262 {
1263 // This vertex was used in the last triangle, 1263 // This vertex was used in the last triangle,
1264 // so it has a fixed score. 1264 // so it has a fixed score.
1265 Score = LastTriScore; 1265 Score = LastTriScore;
1266 } 1266 }
1267 else 1267 else
1268 { 1268 {
1269 // Points for being high in the cache. 1269 // Points for being high in the cache.
1270 const float Scaler = 1.0f / (MaxSizeVertexCache - 3); 1270 const float Scaler = 1.0f / (MaxSizeVertexCache - 3);
1271 Score = 1.0f - (CachePosition - 3) * Scaler; 1271 Score = 1.0f - (CachePosition - 3) * Scaler;
1272 Score = powf(Score, CacheDecayPower); 1272 Score = powf(Score, CacheDecayPower);
1273 } 1273 }
1274 } 1274 }
1275 1275
1276 // Bonus points for having a low number of tris still to 1276 // Bonus points for having a low number of tris still to
1277 // use the vert, so we get rid of lone verts quickly. 1277 // use the vert, so we get rid of lone verts quickly.
1278 float ValenceBoost = powf(v->NumActiveTris, 1278 float ValenceBoost = powf(v->NumActiveTris,
1279 -ValenceBoostPower); 1279 -ValenceBoostPower);
1280 Score += ValenceBoostScale * ValenceBoost; 1280 Score += ValenceBoostScale * ValenceBoost;
1281 1281
1282 return Score; 1282 return Score;
1283} 1283}
1284 1284
1285/* 1285/*
1286 A specialized LRU cache for the Forsyth algorithm. 1286 A specialized LRU cache for the Forsyth algorithm.
1287*/ 1287*/
1288 1288
1289class f_lru 1289class f_lru
1290{ 1290{
1291 1291
1292public: 1292public:
1293 f_lru(vcache *v, tcache *t): vc(v), tc(t) 1293 f_lru(vcache *v, tcache *t): vc(v), tc(t)
1294 { 1294 {
1295 for (u16 i = 0; i < cachesize; i++) 1295 for (u16 i = 0; i < cachesize; i++)
1296 { 1296 {
1297 cache[i] = -1; 1297 cache[i] = -1;
1298 } 1298 }
1299 } 1299 }
1300 1300
1301 // Adds this vertex index and returns the highest-scoring triangle index 1301 // Adds this vertex index and returns the highest-scoring triangle index
1302 u32 add(u16 vert, bool updatetris = false) 1302 u32 add(u16 vert, bool updatetris = false)
1303 { 1303 {
1304 bool found = false; 1304 bool found = false;
1305 1305
1306 // Mark existing pos as empty 1306 // Mark existing pos as empty
1307 for (u16 i = 0; i < cachesize; i++) 1307 for (u16 i = 0; i < cachesize; i++)
1308 { 1308 {
1309 if (cache[i] == vert) 1309 if (cache[i] == vert)
1310 { 1310 {
1311 // Move everything down 1311 // Move everything down
1312 for (u16 j = i; j; j--) 1312 for (u16 j = i; j; j--)
1313 { 1313 {
1314 cache[j] = cache[j - 1]; 1314 cache[j] = cache[j - 1];
1315 } 1315 }
1316 1316
1317 found = true; 1317 found = true;
1318 break; 1318 break;
1319 } 1319 }
1320 } 1320 }
1321 1321
1322 if (!found) 1322 if (!found)
1323 { 1323 {
1324 if (cache[cachesize-1] != -1) 1324 if (cache[cachesize-1] != -1)
1325 vc[cache[cachesize-1]].cachepos = -1; 1325 vc[cache[cachesize-1]].cachepos = -1;
1326 1326
1327 // Move everything down 1327 // Move everything down
1328 for (u16 i = cachesize - 1; i; i--) 1328 for (u16 i = cachesize - 1; i; i--)
1329 { 1329 {
1330 cache[i] = cache[i - 1]; 1330 cache[i] = cache[i - 1];
1331 } 1331 }
1332 } 1332 }
1333 1333
1334 cache[0] = vert; 1334 cache[0] = vert;
1335 1335
1336 u32 highest = 0; 1336 u32 highest = 0;
1337 float hiscore = 0; 1337 float hiscore = 0;
1338 1338
1339 if (updatetris) 1339 if (updatetris)
1340 { 1340 {
1341 // Update cache positions 1341 // Update cache positions
1342 for (u16 i = 0; i < cachesize; i++) 1342 for (u16 i = 0; i < cachesize; i++)
1343 { 1343 {
1344 if (cache[i] == -1) 1344 if (cache[i] == -1)
1345 break; 1345 break;
1346 1346
1347 vc[cache[i]].cachepos = i; 1347 vc[cache[i]].cachepos = i;
1348 vc[cache[i]].score = FindVertexScore(&vc[cache[i]]); 1348 vc[cache[i]].score = FindVertexScore(&vc[cache[i]]);
1349 } 1349 }
1350 1350
1351 // Update triangle scores 1351 // Update triangle scores
1352 for (u16 i = 0; i < cachesize; i++) 1352 for (u16 i = 0; i < cachesize; i++)
1353 { 1353 {
1354 if (cache[i] == -1) 1354 if (cache[i] == -1)
1355 break; 1355 break;
1356 1356
1357 const u16 trisize = vc[cache[i]].tris.size(); 1357 const u16 trisize = vc[cache[i]].tris.size();
1358 for (u16 t = 0; t < trisize; t++) 1358 for (u16 t = 0; t < trisize; t++)
1359 { 1359 {
1360 tcache *tri = &tc[vc[cache[i]].tris[t]]; 1360 tcache *tri = &tc[vc[cache[i]].tris[t]];
1361 1361
1362 tri->score = 1362 tri->score =
1363 vc[tri->ind[0]].score + 1363 vc[tri->ind[0]].score +
1364 vc[tri->ind[1]].score + 1364 vc[tri->ind[1]].score +
1365 vc[tri->ind[2]].score; 1365 vc[tri->ind[2]].score;
1366 1366
1367 if (tri->score > hiscore) 1367 if (tri->score > hiscore)
1368 { 1368 {
1369 hiscore = tri->score; 1369 hiscore = tri->score;
1370 highest = vc[cache[i]].tris[t]; 1370 highest = vc[cache[i]].tris[t];
1371 } 1371 }
1372 } 1372 }
1373 } 1373 }
1374 } 1374 }
1375 1375
1376 return highest; 1376 return highest;
1377 } 1377 }
1378 1378
1379private: 1379private:
1380 s32 cache[cachesize]; 1380 s32 cache[cachesize];
1381 vcache *vc; 1381 vcache *vc;
1382 tcache *tc; 1382 tcache *tc;
1383}; 1383};
1384 1384
1385} // end anonymous namespace 1385} // end anonymous namespace
1386 1386
1387/** 1387/**
1388Vertex cache optimization according to the Forsyth paper: 1388Vertex cache optimization according to the Forsyth paper:
1389http://home.comcast.net/~tom_forsyth/papers/fast_vert_cache_opt.html 1389http://home.comcast.net/~tom_forsyth/papers/fast_vert_cache_opt.html
1390 1390
1391The function is thread-safe (read: you can optimize several meshes in different threads) 1391The function is thread-safe (read: you can optimize several meshes in different threads)
1392 1392
1393\param mesh Source mesh for the operation. */ 1393\param mesh Source mesh for the operation. */
1394IMesh* CMeshManipulator::createForsythOptimizedMesh(const IMesh *mesh) const 1394IMesh* CMeshManipulator::createForsythOptimizedMesh(const IMesh *mesh) const
1395{ 1395{
1396 if (!mesh) 1396 if (!mesh)
1397 return 0; 1397 return 0;
1398 1398
1399 SMesh *newmesh = new SMesh(); 1399 SMesh *newmesh = new SMesh();
1400 newmesh->BoundingBox = mesh->getBoundingBox(); 1400 newmesh->BoundingBox = mesh->getBoundingBox();
1401 1401
1402 const u32 mbcount = mesh->getMeshBufferCount(); 1402 const u32 mbcount = mesh->getMeshBufferCount();
1403 1403
1404 for (u32 b = 0; b < mbcount; ++b) 1404 for (u32 b = 0; b < mbcount; ++b)
1405 { 1405 {
1406 const IMeshBuffer *mb = mesh->getMeshBuffer(b); 1406 const IMeshBuffer *mb = mesh->getMeshBuffer(b);
1407 1407
1408 if (mb->getIndexType() != video::EIT_16BIT) 1408 if (mb->getIndexType() != video::EIT_16BIT)
1409 { 1409 {
1410 os::Printer::log("Cannot optimize a mesh with 32bit indices", ELL_ERROR); 1410 os::Printer::log("Cannot optimize a mesh with 32bit indices", ELL_ERROR);
1411 newmesh->drop(); 1411 newmesh->drop();
1412 return 0; 1412 return 0;
1413 } 1413 }
1414 1414
1415 const u32 icount = mb->getIndexCount(); 1415 const u32 icount = mb->getIndexCount();
1416 const u32 tcount = icount / 3; 1416 const u32 tcount = icount / 3;
1417 const u32 vcount = mb->getVertexCount(); 1417 const u32 vcount = mb->getVertexCount();
1418 const u16 *ind = mb->getIndices(); 1418 const u16 *ind = mb->getIndices();
1419 1419
1420 vcache *vc = new vcache[vcount]; 1420 vcache *vc = new vcache[vcount];
1421 tcache *tc = new tcache[tcount]; 1421 tcache *tc = new tcache[tcount];
1422 1422
1423 f_lru lru(vc, tc); 1423 f_lru lru(vc, tc);
1424 1424
1425 // init 1425 // init
1426 for (u16 i = 0; i < vcount; i++) 1426 for (u16 i = 0; i < vcount; i++)
1427 { 1427 {
1428 vc[i].score = 0; 1428 vc[i].score = 0;
1429 vc[i].cachepos = -1; 1429 vc[i].cachepos = -1;
1430 vc[i].NumActiveTris = 0; 1430 vc[i].NumActiveTris = 0;
1431 } 1431 }
1432 1432
1433 // First pass: count how many times a vert is used 1433 // First pass: count how many times a vert is used
1434 for (u32 i = 0; i < icount; i += 3) 1434 for (u32 i = 0; i < icount; i += 3)
1435 { 1435 {
1436 vc[ind[i]].NumActiveTris++; 1436 vc[ind[i]].NumActiveTris++;
1437 vc[ind[i + 1]].NumActiveTris++; 1437 vc[ind[i + 1]].NumActiveTris++;
1438 vc[ind[i + 2]].NumActiveTris++; 1438 vc[ind[i + 2]].NumActiveTris++;
1439 1439
1440 const u32 tri_ind = i/3; 1440 const u32 tri_ind = i/3;
1441 tc[tri_ind].ind[0] = ind[i]; 1441 tc[tri_ind].ind[0] = ind[i];
1442 tc[tri_ind].ind[1] = ind[i + 1]; 1442 tc[tri_ind].ind[1] = ind[i + 1];
1443 tc[tri_ind].ind[2] = ind[i + 2]; 1443 tc[tri_ind].ind[2] = ind[i + 2];
1444 } 1444 }
1445 1445
1446 // Second pass: list of each triangle 1446 // Second pass: list of each triangle
1447 for (u32 i = 0; i < tcount; i++) 1447 for (u32 i = 0; i < tcount; i++)
1448 { 1448 {
1449 vc[tc[i].ind[0]].tris.push_back(i); 1449 vc[tc[i].ind[0]].tris.push_back(i);
1450 vc[tc[i].ind[1]].tris.push_back(i); 1450 vc[tc[i].ind[1]].tris.push_back(i);
1451 vc[tc[i].ind[2]].tris.push_back(i); 1451 vc[tc[i].ind[2]].tris.push_back(i);
1452 1452
1453 tc[i].drawn = false; 1453 tc[i].drawn = false;
1454 } 1454 }
1455 1455
1456 // Give initial scores 1456 // Give initial scores
1457 for (u16 i = 0; i < vcount; i++) 1457 for (u16 i = 0; i < vcount; i++)
1458 { 1458 {
1459 vc[i].score = FindVertexScore(&vc[i]); 1459 vc[i].score = FindVertexScore(&vc[i]);
1460 } 1460 }
1461 for (u32 i = 0; i < tcount; i++) 1461 for (u32 i = 0; i < tcount; i++)
1462 { 1462 {
1463 tc[i].score = 1463 tc[i].score =
1464 vc[tc[i].ind[0]].score + 1464 vc[tc[i].ind[0]].score +
1465 vc[tc[i].ind[1]].score + 1465 vc[tc[i].ind[1]].score +
1466 vc[tc[i].ind[2]].score; 1466 vc[tc[i].ind[2]].score;
1467 } 1467 }
1468 1468
1469 switch(mb->getVertexType()) 1469 switch(mb->getVertexType())
1470 { 1470 {
1471 case video::EVT_STANDARD: 1471 case video::EVT_STANDARD:
1472 { 1472 {
1473 video::S3DVertex *v = (video::S3DVertex *) mb->getVertices(); 1473 video::S3DVertex *v = (video::S3DVertex *) mb->getVertices();
1474 1474
1475 SMeshBuffer *buf = new SMeshBuffer(); 1475 SMeshBuffer *buf = new SMeshBuffer();
1476 buf->Material = mb->getMaterial(); 1476 buf->Material = mb->getMaterial();
1477 1477
1478 buf->Vertices.reallocate(vcount); 1478 buf->Vertices.reallocate(vcount);
1479 buf->Indices.reallocate(icount); 1479 buf->Indices.reallocate(icount);
1480 1480
1481 core::map<const video::S3DVertex, const u16> sind; // search index for fast operation 1481 core::map<const video::S3DVertex, const u16> sind; // search index for fast operation
1482 typedef core::map<const video::S3DVertex, const u16>::Node snode; 1482 typedef core::map<const video::S3DVertex, const u16>::Node snode;
1483 1483
1484 // Main algorithm 1484 // Main algorithm
1485 u32 highest = 0; 1485 u32 highest = 0;
1486 u32 drawcalls = 0; 1486 u32 drawcalls = 0;
1487 for (;;) 1487 for (;;)
1488 { 1488 {
1489 if (tc[highest].drawn) 1489 if (tc[highest].drawn)
1490 { 1490 {
1491 bool found = false; 1491 bool found = false;
1492 float hiscore = 0; 1492 float hiscore = 0;
1493 for (u32 t = 0; t < tcount; t++) 1493 for (u32 t = 0; t < tcount; t++)
1494 { 1494 {
1495 if (!tc[t].drawn) 1495 if (!tc[t].drawn)
1496 { 1496 {
1497 if (tc[t].score > hiscore) 1497 if (tc[t].score > hiscore)
1498 { 1498 {
1499 highest = t; 1499 highest = t;
1500 hiscore = tc[t].score; 1500 hiscore = tc[t].score;
1501 found = true; 1501 found = true;
1502 } 1502 }
1503 } 1503 }
1504 } 1504 }
1505 if (!found) 1505 if (!found)
1506 break; 1506 break;
1507 } 1507 }
1508 1508
1509 // Output the best triangle 1509 // Output the best triangle
1510 u16 newind = buf->Vertices.size(); 1510 u16 newind = buf->Vertices.size();
1511 1511
1512 snode *s = sind.find(v[tc[highest].ind[0]]); 1512 snode *s = sind.find(v[tc[highest].ind[0]]);
1513 1513
1514 if (!s) 1514 if (!s)
1515 { 1515 {
1516 buf->Vertices.push_back(v[tc[highest].ind[0]]); 1516 buf->Vertices.push_back(v[tc[highest].ind[0]]);
1517 buf->Indices.push_back(newind); 1517 buf->Indices.push_back(newind);
1518 sind.insert(v[tc[highest].ind[0]], newind); 1518 sind.insert(v[tc[highest].ind[0]], newind);
1519 newind++; 1519 newind++;
1520 } 1520 }
1521 else 1521 else
1522 { 1522 {
1523 buf->Indices.push_back(s->getValue()); 1523 buf->Indices.push_back(s->getValue());
1524 } 1524 }
1525 1525
1526 s = sind.find(v[tc[highest].ind[1]]); 1526 s = sind.find(v[tc[highest].ind[1]]);
1527 1527
1528 if (!s) 1528 if (!s)
1529 { 1529 {
1530 buf->Vertices.push_back(v[tc[highest].ind[1]]); 1530 buf->Vertices.push_back(v[tc[highest].ind[1]]);
1531 buf->Indices.push_back(newind); 1531 buf->Indices.push_back(newind);
1532 sind.insert(v[tc[highest].ind[1]], newind); 1532 sind.insert(v[tc[highest].ind[1]], newind);
1533 newind++; 1533 newind++;
1534 } 1534 }
1535 else 1535 else
1536 { 1536 {
1537 buf->Indices.push_back(s->getValue()); 1537 buf->Indices.push_back(s->getValue());
1538 } 1538 }
1539 1539
1540 s = sind.find(v[tc[highest].ind[2]]); 1540 s = sind.find(v[tc[highest].ind[2]]);
1541 1541
1542 if (!s) 1542 if (!s)
1543 { 1543 {
1544 buf->Vertices.push_back(v[tc[highest].ind[2]]); 1544 buf->Vertices.push_back(v[tc[highest].ind[2]]);
1545 buf->Indices.push_back(newind); 1545 buf->Indices.push_back(newind);
1546 sind.insert(v[tc[highest].ind[2]], newind); 1546 sind.insert(v[tc[highest].ind[2]], newind);
1547 } 1547 }
1548 else 1548 else
1549 { 1549 {
1550 buf->Indices.push_back(s->getValue()); 1550 buf->Indices.push_back(s->getValue());
1551 } 1551 }
1552 1552
1553 vc[tc[highest].ind[0]].NumActiveTris--; 1553 vc[tc[highest].ind[0]].NumActiveTris--;
1554 vc[tc[highest].ind[1]].NumActiveTris--; 1554 vc[tc[highest].ind[1]].NumActiveTris--;
1555 vc[tc[highest].ind[2]].NumActiveTris--; 1555 vc[tc[highest].ind[2]].NumActiveTris--;
1556 1556
1557 tc[highest].drawn = true; 1557 tc[highest].drawn = true;
1558 1558
1559 for (u16 j = 0; j < 3; j++) 1559 for (u16 j = 0; j < 3; j++)
1560 { 1560 {
1561 vcache *vert = &vc[tc[highest].ind[j]]; 1561 vcache *vert = &vc[tc[highest].ind[j]];
1562 for (u16 t = 0; t < vert->tris.size(); t++) 1562 for (u16 t = 0; t < vert->tris.size(); t++)
1563 { 1563 {
1564 if (highest == vert->tris[t]) 1564 if (highest == vert->tris[t])
1565 { 1565 {
1566 vert->tris.erase(t); 1566 vert->tris.erase(t);
1567 break; 1567 break;
1568 } 1568 }
1569 } 1569 }
1570 } 1570 }
1571 1571
1572 lru.add(tc[highest].ind[0]); 1572 lru.add(tc[highest].ind[0]);
1573 lru.add(tc[highest].ind[1]); 1573 lru.add(tc[highest].ind[1]);
1574 highest = lru.add(tc[highest].ind[2], true); 1574 highest = lru.add(tc[highest].ind[2], true);
1575 drawcalls++; 1575 drawcalls++;
1576 } 1576 }
1577 1577
1578 buf->setBoundingBox(mb->getBoundingBox()); 1578 buf->setBoundingBox(mb->getBoundingBox());
1579 newmesh->addMeshBuffer(buf); 1579 newmesh->addMeshBuffer(buf);
1580 buf->drop(); 1580 buf->drop();
1581 } 1581 }
1582 break; 1582 break;
1583 case video::EVT_2TCOORDS: 1583 case video::EVT_2TCOORDS:
1584 { 1584 {
1585 video::S3DVertex2TCoords *v = (video::S3DVertex2TCoords *) mb->getVertices(); 1585 video::S3DVertex2TCoords *v = (video::S3DVertex2TCoords *) mb->getVertices();
1586 1586
1587 SMeshBufferLightMap *buf = new SMeshBufferLightMap(); 1587 SMeshBufferLightMap *buf = new SMeshBufferLightMap();
1588 buf->Material = mb->getMaterial(); 1588 buf->Material = mb->getMaterial();
1589 1589
1590 buf->Vertices.reallocate(vcount); 1590 buf->Vertices.reallocate(vcount);
1591 buf->Indices.reallocate(icount); 1591 buf->Indices.reallocate(icount);
1592 1592
1593 core::map<const video::S3DVertex2TCoords, const u16> sind; // search index for fast operation 1593 core::map<const video::S3DVertex2TCoords, const u16> sind; // search index for fast operation
1594 typedef core::map<const video::S3DVertex2TCoords, const u16>::Node snode; 1594 typedef core::map<const video::S3DVertex2TCoords, const u16>::Node snode;
1595 1595
1596 // Main algorithm 1596 // Main algorithm
1597 u32 highest = 0; 1597 u32 highest = 0;
1598 u32 drawcalls = 0; 1598 u32 drawcalls = 0;
1599 for (;;) 1599 for (;;)
1600 { 1600 {
1601 if (tc[highest].drawn) 1601 if (tc[highest].drawn)
1602 { 1602 {
1603 bool found = false; 1603 bool found = false;
1604 float hiscore = 0; 1604 float hiscore = 0;
1605 for (u32 t = 0; t < tcount; t++) 1605 for (u32 t = 0; t < tcount; t++)
1606 { 1606 {
1607 if (!tc[t].drawn) 1607 if (!tc[t].drawn)
1608 { 1608 {
1609 if (tc[t].score > hiscore) 1609 if (tc[t].score > hiscore)
1610 { 1610 {
1611 highest = t; 1611 highest = t;
1612 hiscore = tc[t].score; 1612 hiscore = tc[t].score;
1613 found = true; 1613 found = true;
1614 } 1614 }
1615 } 1615 }
1616 } 1616 }
1617 if (!found) 1617 if (!found)
1618 break; 1618 break;
1619 } 1619 }
1620 1620
1621 // Output the best triangle 1621 // Output the best triangle
1622 u16 newind = buf->Vertices.size(); 1622 u16 newind = buf->Vertices.size();
1623 1623
1624 snode *s = sind.find(v[tc[highest].ind[0]]); 1624 snode *s = sind.find(v[tc[highest].ind[0]]);
1625 1625
1626 if (!s) 1626 if (!s)
1627 { 1627 {
1628 buf->Vertices.push_back(v[tc[highest].ind[0]]); 1628 buf->Vertices.push_back(v[tc[highest].ind[0]]);
1629 buf->Indices.push_back(newind); 1629 buf->Indices.push_back(newind);
1630 sind.insert(v[tc[highest].ind[0]], newind); 1630 sind.insert(v[tc[highest].ind[0]], newind);
1631 newind++; 1631 newind++;
1632 } 1632 }
1633 else 1633 else
1634 { 1634 {
1635 buf->Indices.push_back(s->getValue()); 1635 buf->Indices.push_back(s->getValue());
1636 } 1636 }
1637 1637
1638 s = sind.find(v[tc[highest].ind[1]]); 1638 s = sind.find(v[tc[highest].ind[1]]);
1639 1639
1640 if (!s) 1640 if (!s)
1641 { 1641 {
1642 buf->Vertices.push_back(v[tc[highest].ind[1]]); 1642 buf->Vertices.push_back(v[tc[highest].ind[1]]);
1643 buf->Indices.push_back(newind); 1643 buf->Indices.push_back(newind);
1644 sind.insert(v[tc[highest].ind[1]], newind); 1644 sind.insert(v[tc[highest].ind[1]], newind);
1645 newind++; 1645 newind++;
1646 } 1646 }
1647 else 1647 else
1648 { 1648 {
1649 buf->Indices.push_back(s->getValue()); 1649 buf->Indices.push_back(s->getValue());
1650 } 1650 }
1651 1651
1652 s = sind.find(v[tc[highest].ind[2]]); 1652 s = sind.find(v[tc[highest].ind[2]]);
1653 1653
1654 if (!s) 1654 if (!s)
1655 { 1655 {
1656 buf->Vertices.push_back(v[tc[highest].ind[2]]); 1656 buf->Vertices.push_back(v[tc[highest].ind[2]]);
1657 buf->Indices.push_back(newind); 1657 buf->Indices.push_back(newind);
1658 sind.insert(v[tc[highest].ind[2]], newind); 1658 sind.insert(v[tc[highest].ind[2]], newind);
1659 } 1659 }
1660 else 1660 else
1661 { 1661 {
1662 buf->Indices.push_back(s->getValue()); 1662 buf->Indices.push_back(s->getValue());
1663 } 1663 }
1664 1664
1665 vc[tc[highest].ind[0]].NumActiveTris--; 1665 vc[tc[highest].ind[0]].NumActiveTris--;
1666 vc[tc[highest].ind[1]].NumActiveTris--; 1666 vc[tc[highest].ind[1]].NumActiveTris--;
1667 vc[tc[highest].ind[2]].NumActiveTris--; 1667 vc[tc[highest].ind[2]].NumActiveTris--;
1668 1668
1669 tc[highest].drawn = true; 1669 tc[highest].drawn = true;
1670 1670
1671 for (u16 j = 0; j < 3; j++) 1671 for (u16 j = 0; j < 3; j++)
1672 { 1672 {
1673 vcache *vert = &vc[tc[highest].ind[j]]; 1673 vcache *vert = &vc[tc[highest].ind[j]];
1674 for (u16 t = 0; t < vert->tris.size(); t++) 1674 for (u16 t = 0; t < vert->tris.size(); t++)
1675 { 1675 {
1676 if (highest == vert->tris[t]) 1676 if (highest == vert->tris[t])
1677 { 1677 {
1678 vert->tris.erase(t); 1678 vert->tris.erase(t);
1679 break; 1679 break;
1680 } 1680 }
1681 } 1681 }
1682 } 1682 }
1683 1683
1684 lru.add(tc[highest].ind[0]); 1684 lru.add(tc[highest].ind[0]);
1685 lru.add(tc[highest].ind[1]); 1685 lru.add(tc[highest].ind[1]);
1686 highest = lru.add(tc[highest].ind[2]); 1686 highest = lru.add(tc[highest].ind[2]);
1687 drawcalls++; 1687 drawcalls++;
1688 } 1688 }
1689 1689
1690 buf->setBoundingBox(mb->getBoundingBox()); 1690 buf->setBoundingBox(mb->getBoundingBox());
1691 newmesh->addMeshBuffer(buf); 1691 newmesh->addMeshBuffer(buf);
1692 buf->drop(); 1692 buf->drop();
1693 1693
1694 } 1694 }
1695 break; 1695 break;
1696 case video::EVT_TANGENTS: 1696 case video::EVT_TANGENTS:
1697 { 1697 {
1698 video::S3DVertexTangents *v = (video::S3DVertexTangents *) mb->getVertices(); 1698 video::S3DVertexTangents *v = (video::S3DVertexTangents *) mb->getVertices();
1699 1699
1700 SMeshBufferTangents *buf = new SMeshBufferTangents(); 1700 SMeshBufferTangents *buf = new SMeshBufferTangents();
1701 buf->Material = mb->getMaterial(); 1701 buf->Material = mb->getMaterial();
1702 1702
1703 buf->Vertices.reallocate(vcount); 1703 buf->Vertices.reallocate(vcount);
1704 buf->Indices.reallocate(icount); 1704 buf->Indices.reallocate(icount);
1705 1705
1706 core::map<const video::S3DVertexTangents, const u16> sind; // search index for fast operation 1706 core::map<const video::S3DVertexTangents, const u16> sind; // search index for fast operation
1707 typedef core::map<const video::S3DVertexTangents, const u16>::Node snode; 1707 typedef core::map<const video::S3DVertexTangents, const u16>::Node snode;
1708 1708
1709 // Main algorithm 1709 // Main algorithm
1710 u32 highest = 0; 1710 u32 highest = 0;
1711 u32 drawcalls = 0; 1711 u32 drawcalls = 0;
1712 for (;;) 1712 for (;;)
1713 { 1713 {
1714 if (tc[highest].drawn) 1714 if (tc[highest].drawn)
1715 { 1715 {
1716 bool found = false; 1716 bool found = false;
1717 float hiscore = 0; 1717 float hiscore = 0;
1718 for (u32 t = 0; t < tcount; t++) 1718 for (u32 t = 0; t < tcount; t++)
1719 { 1719 {
1720 if (!tc[t].drawn) 1720 if (!tc[t].drawn)
1721 { 1721 {
1722 if (tc[t].score > hiscore) 1722 if (tc[t].score > hiscore)
1723 { 1723 {
1724 highest = t; 1724 highest = t;
1725 hiscore = tc[t].score; 1725 hiscore = tc[t].score;
1726 found = true; 1726 found = true;
1727 } 1727 }
1728 } 1728 }
1729 } 1729 }
1730 if (!found) 1730 if (!found)
1731 break; 1731 break;
1732 } 1732 }
1733 1733
1734 // Output the best triangle 1734 // Output the best triangle
1735 u16 newind = buf->Vertices.size(); 1735 u16 newind = buf->Vertices.size();
1736 1736
1737 snode *s = sind.find(v[tc[highest].ind[0]]); 1737 snode *s = sind.find(v[tc[highest].ind[0]]);
1738 1738
1739 if (!s) 1739 if (!s)
1740 { 1740 {
1741 buf->Vertices.push_back(v[tc[highest].ind[0]]); 1741 buf->Vertices.push_back(v[tc[highest].ind[0]]);
1742 buf->Indices.push_back(newind); 1742 buf->Indices.push_back(newind);
1743 sind.insert(v[tc[highest].ind[0]], newind); 1743 sind.insert(v[tc[highest].ind[0]], newind);
1744 newind++; 1744 newind++;
1745 } 1745 }
1746 else 1746 else
1747 { 1747 {
1748 buf->Indices.push_back(s->getValue()); 1748 buf->Indices.push_back(s->getValue());
1749 } 1749 }
1750 1750
1751 s = sind.find(v[tc[highest].ind[1]]); 1751 s = sind.find(v[tc[highest].ind[1]]);
1752 1752
1753 if (!s) 1753 if (!s)
1754 { 1754 {
1755 buf->Vertices.push_back(v[tc[highest].ind[1]]); 1755 buf->Vertices.push_back(v[tc[highest].ind[1]]);
1756 buf->Indices.push_back(newind); 1756 buf->Indices.push_back(newind);
1757 sind.insert(v[tc[highest].ind[1]], newind); 1757 sind.insert(v[tc[highest].ind[1]], newind);
1758 newind++; 1758 newind++;
1759 } 1759 }
1760 else 1760 else
1761 { 1761 {
1762 buf->Indices.push_back(s->getValue()); 1762 buf->Indices.push_back(s->getValue());
1763 } 1763 }
1764 1764
1765 s = sind.find(v[tc[highest].ind[2]]); 1765 s = sind.find(v[tc[highest].ind[2]]);
1766 1766
1767 if (!s) 1767 if (!s)
1768 { 1768 {
1769 buf->Vertices.push_back(v[tc[highest].ind[2]]); 1769 buf->Vertices.push_back(v[tc[highest].ind[2]]);
1770 buf->Indices.push_back(newind); 1770 buf->Indices.push_back(newind);
1771 sind.insert(v[tc[highest].ind[2]], newind); 1771 sind.insert(v[tc[highest].ind[2]], newind);
1772 } 1772 }
1773 else 1773 else
1774 { 1774 {
1775 buf->Indices.push_back(s->getValue()); 1775 buf->Indices.push_back(s->getValue());
1776 } 1776 }
1777 1777
1778 vc[tc[highest].ind[0]].NumActiveTris--; 1778 vc[tc[highest].ind[0]].NumActiveTris--;
1779 vc[tc[highest].ind[1]].NumActiveTris--; 1779 vc[tc[highest].ind[1]].NumActiveTris--;
1780 vc[tc[highest].ind[2]].NumActiveTris--; 1780 vc[tc[highest].ind[2]].NumActiveTris--;
1781 1781
1782 tc[highest].drawn = true; 1782 tc[highest].drawn = true;
1783 1783
1784 for (u16 j = 0; j < 3; j++) 1784 for (u16 j = 0; j < 3; j++)
1785 { 1785 {
1786 vcache *vert = &vc[tc[highest].ind[j]]; 1786 vcache *vert = &vc[tc[highest].ind[j]];
1787 for (u16 t = 0; t < vert->tris.size(); t++) 1787 for (u16 t = 0; t < vert->tris.size(); t++)
1788 { 1788 {
1789 if (highest == vert->tris[t]) 1789 if (highest == vert->tris[t])
1790 { 1790 {
1791 vert->tris.erase(t); 1791 vert->tris.erase(t);
1792 break; 1792 break;
1793 } 1793 }
1794 } 1794 }
1795 } 1795 }
1796 1796
1797 lru.add(tc[highest].ind[0]); 1797 lru.add(tc[highest].ind[0]);
1798 lru.add(tc[highest].ind[1]); 1798 lru.add(tc[highest].ind[1]);
1799 highest = lru.add(tc[highest].ind[2]); 1799 highest = lru.add(tc[highest].ind[2]);
1800 drawcalls++; 1800 drawcalls++;
1801 } 1801 }
1802 1802
1803 buf->setBoundingBox(mb->getBoundingBox()); 1803 buf->setBoundingBox(mb->getBoundingBox());
1804 newmesh->addMeshBuffer(buf); 1804 newmesh->addMeshBuffer(buf);
1805 buf->drop(); 1805 buf->drop();
1806 } 1806 }
1807 break; 1807 break;
1808 } 1808 }
1809 1809
1810 delete [] vc; 1810 delete [] vc;
1811 delete [] tc; 1811 delete [] tc;
1812 1812
1813 } // for each meshbuffer 1813 } // for each meshbuffer
1814 1814
1815 return newmesh; 1815 return newmesh;
1816} 1816}
1817 1817
1818} // end namespace scene 1818} // end namespace scene
1819} // end namespace irr 1819} // end namespace irr
1820 1820