Mesh Mesh.cpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. namespace EE{
  4. /******************************************************************************/
  5. DEFINE_CACHE(Mesh, Meshes, MeshPtr, "Mesh");
  6. /******************************************************************************/
  7. // VARIATIONS
  8. /******************************************************************************/
  9. Mesh::Variations::Variations(C Variations &src) : Variations() {T=src;}
  10. void Mesh::Variations::del ( ) {Free(_variation); _variations=0;}
  11. Int Mesh::Variations::alloc(Int variations, Int name_size)
  12. {
  13. del();
  14. Int size=SIZE(Variation)*variations + name_size;
  15. _variations=variations;
  16. _variation =(Variation*)Alloc(size);
  17. return size;
  18. }
  19. Int Mesh::Variations::nameSize ( )C {return _variations ? _variation[_variations-1].name_offset + Length(name(_variations-1))+1 : 0;}
  20. Char8* Mesh::Variations::nameStart( )C {return (Char8*)(_variation+_variations);}
  21. CChar8* Mesh::Variations::name (Int i)C {return InRange(i, _variations) ? nameStart()+_variation[i].name_offset : null;}
  22. UInt Mesh::Variations::id (Int i)C {return InRange(i, _variations) ? _variation[i].id : 0 ;}
  23. void Mesh::Variations::operator=(C Variations &src)
  24. {
  25. if(this!=&src)
  26. {
  27. Int size=alloc(src._variations, src.nameSize());
  28. CopyFast(_variation, src._variation, size);
  29. }
  30. }
  31. Bool Mesh::Variations::save(File &f)C
  32. {
  33. f.cmpUIntV(_variations); if(_variations)
  34. {
  35. Int name_size=nameSize(); f.cmpUIntV(name_size);
  36. FREP(_variations){C Variation &variation=_variation[i]; f<<variation.id; f.cmpUIntV(variation.name_offset);}
  37. f.put(nameStart(), name_size);
  38. }
  39. return f.ok();
  40. }
  41. Bool Mesh::Variations::load(File &f)
  42. {
  43. _variations=f.decUIntV(); if(_variations)
  44. {
  45. Int name_size=f.decUIntV();
  46. alloc(_variations, name_size);
  47. FREP(_variations){Variation &variation=_variation[i]; f>>variation.id; variation.name_offset=f.decUIntV();}
  48. f.get(nameStart(), name_size);
  49. }
  50. if(f.ok())return true;
  51. del(); return false;
  52. }
  53. /******************************************************************************/
  54. static UInt RandomID() // avoid zero as it's reserved for #0 default variation
  55. {
  56. for(;;)if(UInt id=Random())return id;
  57. }
  58. struct VariationEx
  59. {
  60. UInt id;
  61. Str8 name;
  62. void randomizeID() {id=RandomID();}
  63. };
  64. static void GetVariations(Memt<VariationEx> &variations, C Mesh &mesh)
  65. {
  66. variations.setNum(mesh.variations());
  67. REPA(variations)
  68. {
  69. VariationEx &dest=variations[i];
  70. dest.id =mesh.variationID (i);
  71. dest.name=mesh.variationName(i);
  72. }
  73. }
  74. static void SetVariations(Memt<VariationEx> &variations, Mesh &mesh)
  75. {
  76. // we're not setting variation #0
  77. Int name_size=0; for(Int i=1; i<variations.elms(); i++)name_size+=variations[i].name.length()+1;
  78. mesh._variations.alloc(Max(0, variations.elms()-1), name_size);
  79. name_size=0;
  80. Char8 *variation_name=mesh._variations.nameStart();
  81. FREP(mesh._variations._variations)
  82. {
  83. Mesh::Variations::Variation &dest=mesh._variations._variation [i ];
  84. C VariationEx &src = variations[i+1];
  85. Int length_1=src.name.length()+1;
  86. dest.name_offset=name_size;
  87. dest.id =(src.id ? src.id : RandomID());
  88. Set(variation_name, src.name, length_1);
  89. variation_name+=length_1;
  90. name_size +=length_1;
  91. }
  92. }
  93. CChar8* Mesh::variationName( Int i )C {return _variations.name(i-1);} // #0 is default and always null
  94. UInt Mesh::variationID ( Int i )C {return _variations.id (i-1);} // #0 is default and always 0
  95. Int Mesh::variationFind(UInt id)C
  96. {
  97. if(!id)return 0; // #0 is default and always 0
  98. REP(_variations._variations)if(_variations._variation[i].id==id)return i+1;
  99. return -1;
  100. }
  101. Int Mesh::variationFind(CChar8 *name)C
  102. {
  103. if(!Is(name))return 0; // #0 is default and always null
  104. REP(_variations._variations)if(Equal(_variations.name(i), name))return i+1;
  105. return -1;
  106. }
  107. Int Mesh::variations( )C {return _variations._variations+1;}
  108. Mesh& Mesh::variations(Int variations)
  109. {
  110. MAX(variations, 1);
  111. if(T.variations()!=variations)
  112. {
  113. Memt<VariationEx> variation_exs; GetVariations(variation_exs, T);
  114. variation_exs.setNum(variations);
  115. for(Int i=T.variations(); i<variation_exs.elms(); i++)variation_exs[i].randomizeID(); // randomize ID
  116. if(variation_exs.elms()<T.variations())REP(lods()) // minimize mesh part variations
  117. {
  118. MeshLod &lod=T.lod(i); REPA(lod)
  119. {
  120. MeshPart &part=lod.parts[i];
  121. if(part.variations()>variation_exs.elms())part.variations(variation_exs.elms()); // if part has more variations than what we want, then remove the extra
  122. }
  123. }
  124. SetVariations(variation_exs, T);
  125. }
  126. return T;
  127. }
  128. Mesh& Mesh::variationName(Int variation, C Str8 &name)
  129. {
  130. if(variation>0 // can't set name to 0-th default variation
  131. && InRange(variation, variations()))
  132. {
  133. Memt<VariationEx> variations; GetVariations(variations, T);
  134. variations[variation].name=name;
  135. SetVariations(variations, T);
  136. }
  137. return T;
  138. }
  139. Mesh& Mesh::variationRemove(Int variation)
  140. {
  141. if(InRange(variation, variations()) && variations()>1)
  142. {
  143. Int num=T.variations(); REP(lods()){MeshLod &lod=T.lod(i); REPA(lod)lod.parts[i].variations(num).variationRemove(variation);} // allocate all first to make sure others will be processed ok
  144. Memt<VariationEx> variations; GetVariations(variations, T);
  145. variations.remove(variation, true);
  146. SetVariations(variations, T);
  147. }
  148. return T;
  149. }
  150. Mesh& Mesh::variationKeep(Int variation)
  151. {
  152. if(variations()>1)
  153. {
  154. REP(lods()){MeshLod &lod=T.lod(i); REPA(lod)lod.parts[i].variationKeep(variation);}
  155. _variations.del();
  156. }
  157. return T;
  158. }
  159. Mesh& Mesh::variationMove(Int variation, Int new_index)
  160. {
  161. if(InRange(variation, variations()))
  162. {
  163. Clamp(new_index, 0, variations()-1); if(new_index!=variation)
  164. {
  165. Int num=T.variations(); REP(lods()){MeshLod &lod=T.lod(i); REPA(lod)lod.parts[i].variations(num).variationMove(variation, new_index);} // allocate all first to make sure others will be processed ok
  166. Memt<VariationEx> variations; GetVariations(variations, T);
  167. variations.moveElm(variation, new_index);
  168. SetVariations(variations, T);
  169. }
  170. }
  171. return T;
  172. }
  173. /******************************************************************************/
  174. // MANAGE
  175. /******************************************************************************/
  176. void Mesh::zero()
  177. {
  178. ext .zero();
  179. lod_center.zero();
  180. _skeleton =null;
  181. _draw_group_enum=null;
  182. }
  183. Mesh::Mesh() {zero();}
  184. Mesh& Mesh::delBase () {REP(lods())lod(i).delBase (); return T;}
  185. Mesh& Mesh::delRender() {REP(lods())lod(i).delRender(); return T;}
  186. Mesh& Mesh::del ()
  187. {
  188. _lods.del();
  189. super::del();
  190. _bone_map.del();
  191. _variations.del();
  192. zero(); return T;
  193. }
  194. Mesh& Mesh::create(Int parts)
  195. {
  196. del();
  197. super::create(parts);
  198. return T;
  199. }
  200. Mesh& Mesh::create(C Mesh &src, UInt flag_and)
  201. {
  202. if(this==&src)keepOnly(flag_and);else
  203. {
  204. _lods.setNum(src._lods.elms()); FREP(lods())lod(i).create(src.lod(i), flag_and);
  205. copyParams(src);
  206. }
  207. return T;
  208. }
  209. Mesh& Mesh::create(C MeshGroup &src, UInt flag_and)
  210. {
  211. return create(src.meshes.data(), src.meshes.elms(), flag_and);
  212. }
  213. Mesh& Mesh::create(C Mesh *mesh, Int meshes, UInt flag_and)
  214. {
  215. if(!mesh || meshes<=0)del();else
  216. {
  217. Mesh temp, &dest=(InRange(IntPtr(this-mesh), IntPtr(meshes)) ? temp : T); // if 'mesh' array contains 'this' then operate on 'temp' first
  218. Int lods=0; REP(meshes)MAX(lods, mesh[i].lods()); // get max number of LOD's
  219. dest.setLods(lods).copyParams(*mesh); // copy params from first Mesh
  220. REPD(l, dest.lods())
  221. {
  222. MeshLod &lod=dest.lod(l);
  223. Int parts=0; REP(meshes){C Mesh &src_mesh=mesh[i]; if(InRange(l, src_mesh.lods()))parts+=src_mesh.lod(l).parts.elms();} // how many parts for this LOD
  224. lod.parts.setNum(parts); parts=0; // always set LOD parts in case we're operating on MeshGroup that already had some data, and this will clear it
  225. Bool params=true;
  226. FREP(meshes) // add in order
  227. {
  228. C Mesh &src_mesh=mesh[i]; if(InRange(l, src_mesh.lods()))
  229. {
  230. C MeshLod &src_lod=src_mesh.lod(l);
  231. if(params){lod.copyParams(src_lod); params=false;} // copy params from first encountered LOD
  232. FREPA(src_lod)lod.parts[parts++].create(src_lod.parts[i], flag_and);
  233. }
  234. }
  235. }
  236. // at this point 'dest.ext' and 'dest.lod_center' are already set because of earlier 'copyParams', so we can override them only if we want to
  237. Int valid=0; Box box; REP(meshes)
  238. {
  239. C Mesh &src_mesh=mesh[i]; if(src_mesh.vtxs()){if(valid)box|=src_mesh.ext;else {box=src_mesh.ext; dest.lod_center=src_mesh.lod_center;} valid++;} // copy 'lod_center' on first found valid mesh
  240. }
  241. if(valid) // if encountered any valid mesh vtxs (otherwise keep what was already set in 'copyParams')
  242. {
  243. dest.ext=box; if(valid>1)dest.lod_center=dest.ext.pos; // if more than 1 valid mesh, then use box center, if only 1 valid mesh then use its 'lod_center' that we've already set in the loop
  244. }
  245. if(&dest==&temp)Swap(temp, T);
  246. }
  247. return T;
  248. }
  249. void Mesh::copyParams(C Mesh &src)
  250. {
  251. if(this!=&src)
  252. {
  253. ext =src. ext ;
  254. lod_center =src. lod_center;
  255. _skeleton =src._skeleton ;
  256. _draw_group_enum=src._draw_group_enum;
  257. _bone_map =src._bone_map;
  258. _variations =src._variations;
  259. }
  260. }
  261. /******************************************************************************/
  262. Mesh& Mesh::include (UInt flag) {REP(lods())lod(i).include (flag); return T;}
  263. Mesh& Mesh::exclude (UInt flag) {REP(lods())lod(i).exclude (flag); return T;}
  264. Mesh& Mesh::keepOnly(UInt flag) {REP(lods())lod(i).keepOnly(flag); return T;}
  265. /******************************************************************************/
  266. // GET
  267. /******************************************************************************/
  268. UInt Mesh::memUsage()C {UInt size=0; REP(lods())size+=lod(i).memUsage(); return size;}
  269. C MeshLod& Mesh::getDrawLod(C Matrix &matrix)C
  270. {
  271. if(_lods.elms())
  272. {
  273. Flt dist2=GetLodDist2(lod_center, matrix);
  274. REPA(_lods){C MeshLod &test=_lods[i]; if(dist2>=test.dist2)return test;}
  275. }
  276. return T;
  277. }
  278. C MeshLod& Mesh::getDrawLod(C MatrixM &matrix)C
  279. {
  280. if(_lods.elms())
  281. {
  282. Flt dist2=GetLodDist2(lod_center, matrix);
  283. REPA(_lods){C MeshLod &test=_lods[i]; if(dist2>=test.dist2)return test;}
  284. }
  285. return T;
  286. }
  287. Int Mesh::getDrawLodI(C Matrix &matrix)C
  288. {
  289. if(_lods.elms())
  290. {
  291. Flt dist2=GetLodDist2(lod_center, matrix);
  292. REPA(_lods)if(dist2>=_lods[i].dist2)return i+1;
  293. }
  294. return 0;
  295. }
  296. Int Mesh::getDrawLodI(C MatrixM &matrix)C
  297. {
  298. if(_lods.elms())
  299. {
  300. Flt dist2=GetLodDist2(lod_center, matrix);
  301. REPA(_lods)if(dist2>=_lods[i].dist2)return i+1;
  302. }
  303. return 0;
  304. }
  305. C MeshLod& Mesh::getDrawLod (Flt dist2)C {REPA(_lods){C MeshLod &test=_lods[i]; if(dist2>= test .dist2)return test;} return T;}
  306. Int Mesh::getDrawLodI(Flt dist2)C {REPA(_lods) if(dist2>=_lods[i].dist2)return i+1 ; return 0;}
  307. /*Flt Mesh::lodQuality(Int i, Int base)C
  308. {
  309. if(InRange(i, lods()) && InRange(base, lods()))
  310. {
  311. C MeshLod &b=lod(base),
  312. &l=lod(i );
  313. Int v=b.vtxs (),
  314. f=b.trisTotal();
  315. return Avg(v ? Flt(l.vtxs ())/v : 1,
  316. f ? Flt(l.trisTotal())/f : 1);
  317. }
  318. return 0;
  319. }
  320. /******************************************************************************/
  321. // SET
  322. /******************************************************************************/
  323. Mesh& Mesh::setEdgeNormals(Bool flag) {REP(lods())lod(i).setEdgeNormals(flag); return T;}
  324. Mesh& Mesh::setFaceNormals( ) {REP(lods())lod(i).setFaceNormals( ); return T;}
  325. Mesh& Mesh::setNormals2D (Bool flag) {REP(lods())lod(i).setNormals2D (flag); return T;}
  326. Mesh& Mesh::setNormals ( ) {REP(lods())lod(i).setNormals ( ); return T;}
  327. Mesh& Mesh::setTangents ( ) {REP(lods())lod(i).setTangents ( ); return T;}
  328. Mesh& Mesh::setBinormals ( ) {REP(lods())lod(i).setBinormals ( ); return T;}
  329. Mesh& Mesh::setAutoTanBin ( ) {REP(lods())lod(i).setAutoTanBin ( ); return T;}
  330. Bool Mesh::setBox (Bool skip_hidden_parts)
  331. {
  332. Box box; if(getBox(box, skip_hidden_parts))
  333. {
  334. ext =box;
  335. lod_center=ext.pos;
  336. return true;
  337. }
  338. ext .zero();
  339. lod_center.zero();
  340. return false;
  341. }
  342. Mesh& Mesh::setVtxDup2D (UInt flag, Flt pos_eps, Flt nrm_cos) {REP(lods())lod(i).setVtxDup2D (flag, pos_eps, nrm_cos); return T;}
  343. Mesh& Mesh::setVtxDup (UInt flag, Flt pos_eps, Flt nrm_cos) {REP(lods())lod(i).setVtxDup (flag, pos_eps, nrm_cos); return T;}
  344. Mesh& Mesh::setVtxColorAlphaAsTesselationIntensity(Bool tesselate_edges ) {REP(lods())lod(i).setVtxColorAlphaAsTesselationIntensity(tesselate_edges ); return T;}
  345. Mesh& Mesh::setAdjacencies (Bool faces, Bool edges ) {REP(lods())lod(i).setAdjacencies (faces, edges ); return T;}
  346. Mesh& Mesh::setBase (Bool only_if_empty ) {REP(lods())lod(i).setBase (only_if_empty); return T;}
  347. Mesh& Mesh::setRender(Bool optimize ) {REP(lods())lod(i).setRender(optimize, i ); return T;}
  348. Mesh& Mesh::setShader( ) {REP(lods())lod(i).setShader( i ); return T;}
  349. Mesh& Mesh::material (C MaterialPtr &material) {REP(lods())lod(i).material (material, i ); return T;}
  350. /******************************************************************************/
  351. // JOIN / SPLIT
  352. /******************************************************************************/
  353. Mesh& Mesh::join (Int i0, Int i1 , Flt weld_pos_eps) { super::join (i0, i1 , weld_pos_eps); return T;}
  354. Mesh& Mesh::joinAll(Bool test_material, Bool test_draw_group, Bool test_name, UInt test_vtx_flag, Flt weld_pos_eps) {REP(lods())lod(i).joinAll(test_material, test_draw_group, test_name, test_vtx_flag, weld_pos_eps); return T;}
  355. /******************************************************************************/
  356. // TEXTURIZE
  357. /******************************************************************************/
  358. Mesh& Mesh::texMap ( Flt scale , Byte tex_index) {REP(lods())lod(i).texMap (scale , tex_index); return T;}
  359. Mesh& Mesh::texMap (C Matrix &matrix, Byte tex_index) {REP(lods())lod(i).texMap (matrix, tex_index); return T;}
  360. Mesh& Mesh::texMap (C Plane &plane , Byte tex_index) {REP(lods())lod(i).texMap (plane , tex_index); return T;}
  361. Mesh& Mesh::texMap (C Ball &ball , Byte tex_index) {REP(lods())lod(i).texMap (ball , tex_index); return T;}
  362. Mesh& Mesh::texMap (C Tube &tube , Byte tex_index) {REP(lods())lod(i).texMap (tube , tex_index); return T;}
  363. Mesh& Mesh::texMove (C Vec2 &move , Byte tex_index) {REP(lods())lod(i).texMove (move , tex_index); return T;}
  364. Mesh& Mesh::texScale (C Vec2 &scale , Byte tex_index) {REP(lods())lod(i).texScale (scale , tex_index); return T;}
  365. Mesh& Mesh::texRotate( Flt angle , Byte tex_index) {REP(lods())lod(i).texRotate(angle , tex_index); return T;}
  366. /******************************************************************************/
  367. // TRANSFORM
  368. /******************************************************************************/
  369. Mesh& Mesh::move ( C Vec &move ) {REP(lods())lod(i).move ( move); ext+=move; lod_center+=move; return T;}
  370. Mesh& Mesh::scale (C Vec &scale ) {REP(lods())lod(i).scale (scale ); ext*=scale ; lod_center*=scale ; return T;}
  371. Mesh& Mesh::scaleMove (C Vec &scale, C Vec &move ) {REP(lods())lod(i).scaleMove (scale, move); ext*=scale ; ext+=move; lod_center*=scale ; lod_center+=move; return T;}
  372. Mesh& Mesh::scaleMoveBase(C Vec &scale, C Vec &move ) {REP(lods())lod(i).scaleMoveBase(scale, move); ext*=scale ; ext+=move; lod_center*=scale ; lod_center+=move; return T;}
  373. Mesh& Mesh::transform (C Matrix3 &matrix ) {REP(lods())lod(i).transform (matrix ); ext*=matrix; lod_center*=matrix; return T;}
  374. Mesh& Mesh::transform (C Matrix &matrix ) {REP(lods())lod(i).transform (matrix ); ext*=matrix; lod_center*=matrix; return T;}
  375. Mesh& Mesh::animate (C MemPtrN<Matrix, 256> &matrixes) {REP(lods())lod(i).animate (matrixes ); setBox(); return T;}
  376. Mesh& Mesh::animate (C AnimatedSkeleton &skel ) {REP(lods())lod(i).animate (skel ); setBox(); return T;}
  377. Mesh& Mesh::setSize (C Box &box )
  378. {
  379. Vec size=T.ext.size(),
  380. scale((size.x>EPS) ? box.w()/size.x : 0,
  381. (size.y>EPS) ? box.h()/size.y : 0,
  382. (size.z>EPS) ? box.d()/size.z : 0),
  383. move=box.min-T.ext.min()*scale;
  384. scaleMove(scale, move);
  385. return T;
  386. }
  387. Mesh& Mesh::mirrorX () {REP(lods())lod(i).mirrorX (); ext.mirrorX (); CHS(lod_center.x); return T;}
  388. Mesh& Mesh::mirrorY () {REP(lods())lod(i).mirrorY (); ext.mirrorY (); CHS(lod_center.y); return T;}
  389. Mesh& Mesh::mirrorZ () {REP(lods())lod(i).mirrorZ (); ext.mirrorZ (); CHS(lod_center.z); return T;}
  390. Mesh& Mesh::reverse () {REP(lods())lod(i).reverse (); return T;}
  391. Mesh& Mesh::rightToLeft() {REP(lods())lod(i).rightToLeft(); ext.rightToLeft(); lod_center.rightToLeft(); return T;}
  392. /******************************************************************************/
  393. // OPERATIONS
  394. /******************************************************************************/
  395. Mesh& Mesh::weldVtx2D (UInt flag, Flt pos_eps, Flt nrm_cos, Flt remove_degenerate_faces_eps) {REP(lods())lod(i).weldVtx2D (flag, pos_eps, nrm_cos, remove_degenerate_faces_eps); return T;}
  396. Mesh& Mesh::weldVtx (UInt flag, Flt pos_eps, Flt nrm_cos, Flt remove_degenerate_faces_eps) {REP(lods())lod(i).weldVtx (flag, pos_eps, nrm_cos, remove_degenerate_faces_eps); return T;}
  397. Mesh& Mesh::weldVtxValues(UInt flag, Flt pos_eps, Flt nrm_cos, Flt remove_degenerate_faces_eps) {REP(lods())lod(i).weldVtxValues(flag, pos_eps, nrm_cos, remove_degenerate_faces_eps); return T;}
  398. Mesh& Mesh::weldEdge () {REP(lods())lod(i).weldEdge (); return T;}
  399. Mesh& Mesh::tesselate() {REP(lods())lod(i).tesselate(); return T;}
  400. Mesh& Mesh::subdivide() {REP(lods())lod(i).subdivide(); return T;}
  401. Int Mesh::boneFind(CChar8 *bone_name)C {return _bone_map.find(bone_name);}
  402. //Bool boneRename(C Str8 &src, C Str8 &dest ) ; // rename 'src' bone to 'dest' bone, returns true if a bone was renamed
  403. //Bool Mesh::boneRename(C Str8 &src, C Str8 &dest) {return _bone_map.rename(src, dest);}
  404. Mesh& Mesh::boneRemap(C MemPtr<Byte, 256> &old_to_new, Bool remap_names)
  405. {
  406. REP(lods())lod(i).boneRemap(old_to_new);
  407. if(remap_names)_bone_map.remap(old_to_new);
  408. return T;
  409. }
  410. void Mesh::includeUsedBones(Bool (&bones)[256])C {REP(lods())lod(i).includeUsedBones(bones);}
  411. void Mesh:: setUsedBones(Bool (&bones)[256])C {Zero(bones); includeUsedBones(bones);}
  412. Mesh& Mesh::setVtxAO(Flt strength, Flt bias, Flt max, Flt ray_length, Flt pos_eps, Int rays, MESH_AO_FUNC func, Threads *threads) {REP(lods())lod(i).setVtxAO(strength, bias, max, ray_length, pos_eps, rays, func, threads); return T;}
  413. Mesh& Mesh::freeOpenGLESData() {REP(lods())lod(i).freeOpenGLESData(); return T;}
  414. /******************************************************************************/
  415. // FIX
  416. /******************************************************************************/
  417. Mesh& Mesh::fixTexWrapping(Byte tex_index) {REP(lods())lod(i).fixTexWrapping(tex_index); return T;}
  418. Mesh& Mesh::fixTexOffset (Byte tex_index) {REP(lods())lod(i).fixTexOffset (tex_index); return T;}
  419. /******************************************************************************/
  420. // CONVERT
  421. /******************************************************************************/
  422. Mesh& Mesh::edgeToDepth(Bool tex_align) {REP(lods())lod(i).edgeToDepth(tex_align); return T;}
  423. Mesh& Mesh::edgeToTri (Bool set_id ) {REP(lods())lod(i).edgeToTri (set_id ); return T;}
  424. Mesh& Mesh::triToQuad (Flt cos ) {REP(lods())lod(i).triToQuad (cos ); return T;}
  425. Mesh& Mesh::quadToTri (Flt cos ) {REP(lods())lod(i).quadToTri (cos ); return T;}
  426. /******************************************************************************/
  427. // ADD / REMOVE
  428. /******************************************************************************/
  429. MeshLod& Mesh::newLod()
  430. {
  431. MeshLod &last=_lods.New();
  432. MeshLod &prev= lod(lods()-2);
  433. last.copyParams(prev);
  434. return last;
  435. }
  436. MeshLod& Mesh::newLod(Int i)
  437. {
  438. Clamp(i, 0, lods());
  439. MeshLod &lod=_lods.NewAt(i-1);
  440. if(!i)
  441. {
  442. MeshLod &prev=T;
  443. lod.copyParams(prev);
  444. Swap(prev, lod);
  445. return T;
  446. }else
  447. {
  448. MeshLod &prev=T.lod(i-1);
  449. lod.copyParams(prev);
  450. return lod;
  451. }
  452. }
  453. Mesh& Mesh::add(C MeshBase &src)
  454. {
  455. Box box; Bool valid_box=src.getBox(box), this_box=(vtxs()>0);
  456. super::add(src);
  457. if(valid_box)
  458. {
  459. if(this_box)T.ext|=box;else T.ext=box; lod_center=T.ext.pos;
  460. }
  461. return T;
  462. }
  463. Mesh& Mesh::add(C MeshPart &src)
  464. {
  465. Box box; Bool valid_box=src.getBox(box), this_box=(vtxs()>0);
  466. super::add(src);
  467. if(valid_box)
  468. {
  469. if(this_box)T.ext|=box;else T.ext=box; lod_center=T.ext.pos;
  470. }
  471. return T;
  472. }
  473. Mesh& Mesh::variationInclude(C Mesh &src)
  474. {
  475. FREP(src.variations())if(variationFind(src.variationName(i))<0) // add in same order
  476. {
  477. variations (variations()+1); // create new one
  478. variationName(variations()-1, src.variationName(i)); // set name
  479. }
  480. return T;
  481. }
  482. Mesh& Mesh::add(C Mesh &src)
  483. {
  484. if(!is())copyParams(src);else
  485. {
  486. if(src.vtxs())
  487. {
  488. if(vtxs()){ext|=src.ext; lod_center= ext.pos ;}
  489. else {ext =src.ext; lod_center=src.lod_center;}
  490. }
  491. variationInclude(src);
  492. }
  493. if(src.lods()>lods())setLods(src.lods()); // make room for LOD's
  494. FREP(src.lods())lod(i).add(src.lod(i), &src, this);
  495. return T;
  496. }
  497. Mesh& Mesh::remove(Int i, Bool set_box)
  498. {
  499. if(InRange(i, T))
  500. {
  501. parts.remove(i, true);
  502. if(set_box)setBox();
  503. }
  504. return T;
  505. }
  506. Mesh& Mesh::removeLod(Int i)
  507. {
  508. if(InRange(i, lods()))
  509. {
  510. if(i)_lods.remove(i-1, true);else
  511. if( !_lods.elms())del();else
  512. {
  513. Swap(SCAST(MeshLod, T), _lods[0]); // move #0 to T
  514. //dist2=0; // since it's now the main LOD, then clear its distance, this is to keep consistency about Main LOD being at distance 0
  515. _lods.remove(0, true);
  516. }
  517. }
  518. return T;
  519. }
  520. Mesh& Mesh::setLods(Int n)
  521. {
  522. if(n<=0)del();else _lods.setNum(n-1);
  523. return T;
  524. }
  525. /******************************************************************************/
  526. // OPTIMIZE
  527. /******************************************************************************/
  528. Mesh& Mesh::removeDoubleEdges ( ) { REP(lods()) lod(i).removeDoubleEdges ( ); return T;}
  529. Mesh& Mesh::removeDegenerateFaces(Flt eps ) { REP(lods()) lod(i).removeDegenerateFaces(eps ); return T;}
  530. Bool Mesh::removeUnusedVtxs (Bool include_edge_references, Bool set_box ) {Bool changed=false; REP(lods())changed|=lod(i).removeUnusedVtxs (include_edge_references ); if(changed && set_box)setBox(); return changed;}
  531. Mesh& Mesh::removeSingleFaces (Flt fraction ) { REP(lods()) lod(i).removeSingleFaces (fraction ); return T;}
  532. Mesh& Mesh::weldInlineEdges (Flt cos_edge, Flt cos_vtx, Bool z_test ) { REP(lods()) lod(i).weldInlineEdges (cos_edge, cos_vtx, z_test ); return T;}
  533. Mesh& Mesh::weldCoplanarFaces (Flt cos_face, Flt cos_vtx, Bool safe, Flt max_face_length) { REP(lods()) lod(i).weldCoplanarFaces (cos_face, cos_vtx, safe, max_face_length); return T;}
  534. Mesh& Mesh::sortByMaterials ( ) { REP(lods()) lod(i).sortByMaterials ( ); return T;}
  535. Mesh& Mesh::simplify(Flt intensity, Flt max_distance, Flt max_uv, Flt max_color, Flt max_material, Flt max_skin, Flt max_normal, Bool keep_border, MESH_SIMPLIFY mode, Flt pos_eps, Mesh *dest, Bool *stop)
  536. {
  537. if(!dest)dest=this;
  538. if( dest!=this)
  539. {
  540. dest->copyParams(T);
  541. dest->setLods(lods());
  542. }
  543. REP(lods()) // go from the end so we can remove lod's if needed
  544. {
  545. MeshLod &dest_lod=dest->lod(i);
  546. lod(i).simplify(intensity, max_distance, max_uv, max_color, max_material, max_skin, max_normal, keep_border, mode, pos_eps, &dest_lod, stop); if(stop && *stop)break;
  547. if(!dest_lod.is())dest->removeLod(i); // if became empty, then just remove it
  548. }
  549. return *dest;
  550. }
  551. /******************************************************************************/
  552. //
  553. /******************************************************************************/
  554. Mesh& Mesh::skeleton(Skeleton *skeleton, Bool by_name)
  555. {
  556. T._skeleton=skeleton;
  557. if(skeleton && skeleton->is() && !_bone_map.same(*skeleton)) // remap only if new skeleton exists (in case it failed to load, then it could be null or have no bones, or the parameter could just have been specifically set to null in order to clear the skeleton link) and if the existing bone map is different than of the new skeleton
  558. {
  559. if(_bone_map.is()) // remap vertexes only if the mesh already had a bone map (otherwise the vertex bone could be set, but the bone map doesn't exist yet, and in that case the vertex bone data could be lost if we've performed remapping)
  560. {
  561. Memt<Byte, 256> old_to_new;
  562. _bone_map.setRemap(*skeleton, old_to_new, by_name);
  563. boneRemap(old_to_new, false); // set false to not waste time on adjusting the '_bone_map' itself, because we're going to recreate it anyway below
  564. }
  565. // setup new mesh bone info
  566. _bone_map.create(*skeleton);
  567. }
  568. return T;
  569. }
  570. Mesh& Mesh::clearSkeleton()
  571. {
  572. _skeleton=null;
  573. _bone_map.del();
  574. return T;
  575. }
  576. Bool Mesh::hasDrawGroup ( Int draw_group_index)C {REP(lods())if(lod(i).hasDrawGroup (draw_group_index))return true; return false;}
  577. Bool Mesh::hasDrawGroupMask(UInt draw_group_mask )C {REP(lods())if(lod(i).hasDrawGroupMask(draw_group_mask ))return true; return false;}
  578. Mesh& Mesh:: drawGroupEnum(Enum *e, Bool reset_when_not_found)
  579. {
  580. T._draw_group_enum=e;
  581. REP(lods())
  582. {
  583. MeshLod &lod=T.lod(i); REPA(lod)
  584. {
  585. MeshPart &part=lod.parts[i];
  586. Int enum_index=(e ? e->findByIDUInt(part._draw_mask_enum_id) : -1); // find that enum
  587. if(InRange(enum_index, 32))part._draw_mask=IndexToFlag(enum_index);else // if enum found then adjust the draw mask
  588. if(reset_when_not_found )part._draw_mask=IndexToFlag(0); // otherwise reset or keep
  589. }
  590. }
  591. return T;
  592. }
  593. /******************************************************************************/
  594. }
  595. /******************************************************************************/