CMeshManipulator.cpp 45 KB

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