Mshb Set.cpp 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. namespace EE{
  4. /******************************************************************************/
  5. // GET
  6. /******************************************************************************/
  7. Int MeshBase::maxId()C
  8. {
  9. Int max=-1;
  10. if(edge.id())REPA(edge)MAX(max, edge.id(i));
  11. if(tri .id())REPA(tri )MAX(max, tri .id(i));
  12. if(quad.id())REPA(quad)MAX(max, quad.id(i));
  13. return max;
  14. }
  15. Bool MeshBase::hasId(Int id)C
  16. {
  17. if(edge.id())REPA(edge)if(edge.id(i)==id)return true;
  18. if(tri .id())REPA(tri )if(tri .id(i)==id)return true;
  19. if(quad.id())REPA(quad)if(quad.id(i)==id)return true;
  20. return false;
  21. }
  22. /******************************************************************************/
  23. Bool MeshBase::getRect(Rect &rect)C
  24. {
  25. Box box; Bool ret=getBox(box);
  26. rect.min=box.min.xy;
  27. rect.max=box.max.xy;
  28. return ret;
  29. }
  30. Bool MeshBase::getRectXZ(Rect &rect)C
  31. {
  32. Box box; Bool ret=getBox(box);
  33. rect.min=box.min.xz();
  34. rect.max=box.max.xz();
  35. return ret;
  36. }
  37. Bool MeshBase::getBox (Box &box )C {return box .from(vtx.pos(), vtxs());}
  38. Bool MeshBase::getBox (Box &box , C Matrix &mesh_matrix)C {return box .from(vtx.pos(), vtxs(), mesh_matrix);}
  39. Bool MeshBase::getBall(Ball &ball )C {return ball.from(vtx.pos(), vtxs());}
  40. Flt MeshBase::area(Vec *center)C
  41. {
  42. if(center)center->zero();
  43. Flt area=0;
  44. if(C Vec *vtx=T.vtx.pos())
  45. {
  46. REPA(tri)
  47. {
  48. C VecI &f=tri.ind(i); Tri t(vtx[f.x], vtx[f.y], vtx[f.z]);
  49. Flt a=t.area();
  50. area +=a;
  51. if(center)*center+=a*t.center();
  52. }
  53. REPA(quad)
  54. {
  55. C VecI4 &f=quad.ind(i); Quad q(vtx[f.x], vtx[f.y], vtx[f.z], vtx[f.w]);
  56. Flt a=q.area();
  57. area +=a;
  58. if(center)*center+=a*q.center();
  59. }
  60. }
  61. if(center && area)*center/=area;
  62. return area;
  63. }
  64. /******************************************************************************/
  65. Flt MeshBase::convexVolume()C
  66. {
  67. Flt vol=0;
  68. Box box; if(getBox(box))
  69. {
  70. C Vec *pos=vtx.pos(); // 'getBox' implies "vtx.pos()!=null"
  71. Vec center=box.center();
  72. REPA(tri)
  73. {
  74. C VecI &ind=tri.ind(i);
  75. vol+=TetraVolume(pos[ind.x], pos[ind.y], pos[ind.z], center);
  76. }
  77. REPA(quad)
  78. {
  79. C VecI4 &ind=quad.ind(i);
  80. vol+=TetraVolume(pos[ind.x], pos[ind.y], pos[ind.w], center);
  81. vol+=TetraVolume(pos[ind.w], pos[ind.y], pos[ind.z], center);
  82. }
  83. }
  84. return vol;
  85. }
  86. /******************************************************************************/
  87. // SET
  88. /******************************************************************************/
  89. MeshBase& MeshBase::setEdgeNormals(Bool flag)
  90. {
  91. exclude(FACE_NRM);
  92. include(EDGE_NRM);
  93. if(flag && !edge.flag())flag=false;
  94. REPA(edge)
  95. {
  96. Int *p =edge.ind(i).c;
  97. Int dir=1;
  98. if(flag)switch(edge.flag(i)&ETQ_LR)
  99. {
  100. case 0 :
  101. case ETQ_LR: dir= 0; break;
  102. case ETQ_L : dir=-1; break;
  103. }
  104. switch(dir)
  105. {
  106. case 0: edge.nrm(i).zero(); break;
  107. case -1: edge.nrm(i).set (PerpN(vtx.pos(p[0]).xy-vtx.pos(p[1]).xy), 0); break;
  108. case +1: edge.nrm(i).set (PerpN(vtx.pos(p[1]).xy-vtx.pos(p[0]).xy), 0); break;
  109. }
  110. }
  111. return T;
  112. }
  113. MeshBase& MeshBase::setFaceNormals()
  114. {
  115. if(vtx.pos())
  116. {
  117. exclude(EDGE_NRM);
  118. include(FACE_NRM);
  119. if(VecI *_tri =tri .ind()){Vec *nrm=tri .nrm(); REPA(tri ){Int *p=(_tri ++)->c; *nrm++=GetNormal(vtx.pos(p[0]), vtx.pos(p[1]), vtx.pos(p[2]));}}
  120. if(VecI4 *_quad=quad.ind()){Vec *nrm=quad.nrm(); REPA(quad){Int *p=(_quad++)->c; *nrm++=GetNormal(vtx.pos(p[0]), vtx.pos(p[1]), vtx.pos(p[3]));}}
  121. }
  122. return T;
  123. }
  124. MeshBase& MeshBase::setNormals2D(Bool flag)
  125. {
  126. setEdgeNormals(flag);
  127. include(VTX_NRM); ZeroN(vtx.nrm(), vtxs());
  128. VecI2 *_edge=edge.ind();
  129. Vec * nrm =edge.nrm(); REPA(edge)
  130. {
  131. VecI2 f=*_edge++; f.remap(vtx.dup());
  132. vtx.nrm(f.c[0])+=*nrm;
  133. vtx.nrm(f.c[1])+=*nrm++;
  134. }
  135. Normalize(vtx.nrm(), vtxs());
  136. if(vtx.dup())REPA(vtx)vtx.nrm(i)=vtx.nrm(vtx.dup(i));
  137. return T;
  138. }
  139. MeshBase& MeshBase::setNormals()
  140. {
  141. include(VTX_NRM); ZeroN(vtx.nrm(), vtxs());
  142. #if 1 // weighted normal depending on face surface area (that's why there's 'GetNormalU')
  143. REPA(tri)
  144. {
  145. VecI f =tri.ind(i); f.remap(vtx.dup());
  146. Vec nrm=GetNormalU(vtx.pos(f.c[0]), vtx.pos(f.c[1]), vtx.pos(f.c[2]));
  147. vtx.nrm(f.c[0])+=nrm;
  148. vtx.nrm(f.c[1])+=nrm;
  149. vtx.nrm(f.c[2])+=nrm;
  150. }
  151. REPA(quad)
  152. {
  153. VecI4 f =quad.ind(i); f.remap(vtx.dup());
  154. Vec &v0=vtx.pos(f.c[0]),
  155. &v1=vtx.pos(f.c[1]),
  156. &v2=vtx.pos(f.c[2]),
  157. &v3=vtx.pos(f.c[3]),
  158. nrm=GetNormalU(v0, v1, v3)+GetNormalU(v1, v2, v3);
  159. vtx.nrm(f.c[0])+=nrm;
  160. vtx.nrm(f.c[1])+=nrm;
  161. vtx.nrm(f.c[2])+=nrm;
  162. vtx.nrm(f.c[3])+=nrm;
  163. }
  164. Normalize(vtx.nrm(), vtxs());
  165. #elif 1 // weighted normal depending on face angle
  166. REPA(tri)
  167. {
  168. VecI f =tri.ind(i); f.remap(vtx.dup());
  169. Vec &v0 =vtx.pos(f.c[0]),
  170. &v1 =vtx.pos(f.c[1]),
  171. &v2 =vtx.pos(f.c[2]),
  172. nrm=GetNormal(v0, v1, v2);
  173. Flt a0 =AbsAngleBetween(v2, v0, v1),
  174. a1 =AbsAngleBetween(v0, v1, v2), a2=PI-a0-a1;
  175. vtx.nrm(f.c[0])+=a0*nrm;
  176. vtx.nrm(f.c[1])+=a1*nrm;
  177. vtx.nrm(f.c[2])+=a2*nrm;
  178. }
  179. REPA(quad)
  180. {
  181. VecI4 f =quad.ind(i); f.remap(vtx.dup());
  182. Vec &v0 =vtx.pos(f.c[0]),
  183. &v1 =vtx.pos(f.c[1]),
  184. &v2 =vtx.pos(f.c[2]),
  185. &v3 =vtx.pos(f.c[3]),
  186. nrm013=GetNormal(v0, v1, v3),
  187. nrm123=GetNormal(v1, v2, v3);
  188. Flt a301 =AbsAngleBetween(v3, v0, v1),
  189. a013 =AbsAngleBetween(v0, v1, v3), a130=PI-a301-a013,
  190. a123 =AbsAngleBetween(v1, v2, v3),
  191. a231 =AbsAngleBetween(v2, v3, v1), a312=PI-a123-a231;
  192. vtx.nrm(f.c[0])+=a301*nrm013;
  193. vtx.nrm(f.c[1])+=a013*nrm013 + a312*nrm123;
  194. vtx.nrm(f.c[2])+= + a123*nrm123;
  195. vtx.nrm(f.c[3])+=a130*nrm013 + a231*nrm123;
  196. }
  197. Normalize(vtx.nrm(), vtxs());
  198. #else // calculate using Quadrics (this is only for testing)
  199. Memt<QuadricMatrix> vtx_qm; vtx_qm.setNumZero(vtxs());
  200. REPA(tri)
  201. {
  202. VecI f =tri.ind(i); f.remap(vtx.dup());
  203. Vec &v0 =vtx.pos(f.c[0]),
  204. &v1 =vtx.pos(f.c[1]),
  205. &v2 =vtx.pos(f.c[2]),
  206. nrm =GetNormalU(v0, v1, v2);
  207. Flt weight=nrm.normalize();
  208. QuadricMatrix qm(nrm, v0); qm*=weight;
  209. vtx_qm[f.c[0]]+=qm;
  210. vtx_qm[f.c[1]]+=qm;
  211. vtx_qm[f.c[2]]+=qm;
  212. }
  213. REPA(quad)
  214. {
  215. VecI4 f =quad.ind(i); f.remap(vtx.dup());
  216. Vec &v0 =vtx.pos(f.c[0]),
  217. &v1 =vtx.pos(f.c[1]),
  218. &v2 =vtx.pos(f.c[2]),
  219. &v3 =vtx.pos(f.c[3]),
  220. nrm013=GetNormalU(v0, v1, v3),
  221. nrm123=GetNormalU(v1, v2, v3);
  222. Flt weight013=nrm013.normalize(),
  223. weight123=nrm123.normalize();
  224. QuadricMatrix qm013(nrm013, v0); qm013*=weight013;
  225. QuadricMatrix qm123(nrm123, v1); qm123*=weight123;
  226. vtx_qm[f.c[0]]+=qm013;
  227. vtx_qm[f.c[1]]+=qm013+qm123;
  228. vtx_qm[f.c[2]]+= qm123;
  229. vtx_qm[f.c[3]]+=qm013+qm123;
  230. }
  231. REPA(vtx)vtx.nrm(i)=vtx_qm[i].normal(vtx.pos(i)+offset); // <- here we would have to use some offset because normal at the surface is not precise, best offset is vtx.nrm which we're trying to calculate
  232. #endif
  233. if(vtx.dup())REPA(vtx)vtx.nrm(i)=vtx.nrm(vtx.dup(i));
  234. return T;
  235. }
  236. /******************************************************************************/
  237. MeshBase& MeshBase::setTangents()
  238. {
  239. if(C Vec *pos=vtx.pos ())
  240. if(C Vec2 *tex=vtx.tex0())
  241. {
  242. include(VTX_TAN); ZeroN(vtx.tan(), vtxs());
  243. if(VecI *_tri=tri.ind())REPA(tri)
  244. {
  245. VecI f =*_tri++;
  246. Vec2 t0=tex[f.x],
  247. ta=tex[f.y]-t0,
  248. tb=tex[f.z]-t0;
  249. Flt u, v;
  250. // u*ta + v*tb = Vec2(1, 0)
  251. // u*ta.x + v*tb.x = 1
  252. // u*ta.y + v*tb.y = 0
  253. if(Solve(ta.x, ta.y, tb.x, tb.y, 1, 0, u, v)==1)
  254. {
  255. C Vec &p0 =pos[f.x],
  256. &p1 =pos[f.y],
  257. &p2 =pos[f.z],
  258. p01=p1-p0,
  259. p02=p2-p0;
  260. Vec tan=p01*u + p02*v;
  261. // Flt Tri::area()C {return 0.5f*Cross(p[1]-p[0], p[2]-p[0]).length();}
  262. tan.setLength(Cross(p01, p02).length());
  263. vtx.tan(f.x)+=tan;
  264. vtx.tan(f.y)+=tan;
  265. vtx.tan(f.z)+=tan;
  266. }
  267. }
  268. if(VecI4 *_quad=quad.ind())REPA(quad)
  269. {
  270. VecI4 f =*_quad++;
  271. Vec2 t0=tex[f.x],
  272. ta=tex[f.y]-t0,
  273. tb=tex[f.w]-t0;
  274. Flt u, v;
  275. if(Solve(ta.x, ta.y, tb.x, tb.y, 1, 0, u, v)==1)
  276. {
  277. C Vec &p0 =pos[f.x],
  278. &p1 =pos[f.y],
  279. &p2 =pos[f.z],
  280. &p3 =pos[f.w],
  281. p01=p1-p0,
  282. p03=p3-p0,
  283. p12=p2-p1,
  284. p13=p3-p1;
  285. Vec tan=p01*u + p03*v;
  286. // Flt Quad::area()C {return 0.5f*(Cross(p[1]-p[0], p[3]-p[0]).length()+Cross(p[2]-p[1], p[3]-p[1]).length());}
  287. tan.setLength(Cross(p01, p03).length() + Cross(p12, p13).length());
  288. vtx.tan(f.x)+=tan;
  289. vtx.tan(f.y)+=tan;
  290. vtx.tan(f.z)+=tan;
  291. vtx.tan(f.w)+=tan;
  292. }
  293. }
  294. REPA(vtx)
  295. {
  296. Vec &tan=vtx.tan(i); if(!tan.normalize()) // !! valid non-zero tangent must be set because otherwise triangles can become black !!
  297. {
  298. if(vtx.nrm())tan=PerpN(vtx.nrm(i));
  299. else tan.set(1, 0, 0);
  300. }
  301. }
  302. }
  303. return T;
  304. }
  305. MeshBase& MeshBase::setBinormals()
  306. {
  307. if(C Vec *pos=vtx.pos ())
  308. if(C Vec2 *tex=vtx.tex0())
  309. {
  310. include(VTX_BIN); ZeroN(vtx.bin(), vtxs());
  311. if(VecI *_tri=tri.ind())REPA(tri)
  312. {
  313. VecI f =*_tri++;
  314. Vec2 t0=tex[f.x],
  315. ta=tex[f.y]-t0,
  316. tb=tex[f.z]-t0;
  317. Flt u, v;
  318. // u*ta + v*tb = Vec2(0, 1)
  319. // u*ta.x + v*tb.x = 0
  320. // u*ta.y + v*tb.y = 1
  321. if(Solve(ta.x, ta.y, tb.x, tb.y, 0, 1, u, v)==1)
  322. {
  323. C Vec &p0 =pos[f.x],
  324. &p1 =pos[f.y],
  325. &p2 =pos[f.z],
  326. p01=p1-p0,
  327. p02=p2-p0;
  328. Vec bin=p01*u + p02*v;
  329. // Flt Tri::area()C {return 0.5f*Cross(p[1]-p[0], p[2]-p[0]).length();}
  330. bin.setLength(Cross(p01, p02).length());
  331. vtx.bin(f.x)+=bin;
  332. vtx.bin(f.y)+=bin;
  333. vtx.bin(f.z)+=bin;
  334. }
  335. }
  336. if(VecI4 *_quad=quad.ind())REPA(quad)
  337. {
  338. VecI4 f =*_quad++;
  339. Vec2 t0=tex[f.x],
  340. ta=tex[f.y]-t0,
  341. tb=tex[f.w]-t0;
  342. Flt u, v;
  343. if(Solve(ta.x, ta.y, tb.x, tb.y, 0, 1, u, v)==1)
  344. {
  345. C Vec &p0 =pos[f.x],
  346. &p1 =pos[f.y],
  347. &p2 =pos[f.z],
  348. &p3 =pos[f.w],
  349. p01=p1-p0,
  350. p03=p3-p0,
  351. p12=p2-p1,
  352. p13=p3-p1;
  353. Vec bin=p01*u + p03*v;
  354. // Flt Quad::area()C {return 0.5f*(Cross(p[1]-p[0], p[3]-p[0]).length()+Cross(p[2]-p[1], p[3]-p[1]).length());}
  355. bin.setLength(Cross(p01, p03).length() + Cross(p12, p13).length());
  356. vtx.bin(f.x)+=bin;
  357. vtx.bin(f.y)+=bin;
  358. vtx.bin(f.z)+=bin;
  359. vtx.bin(f.w)+=bin;
  360. }
  361. }
  362. REPA(vtx)
  363. {
  364. Vec &bin=vtx.bin(i); if(!bin.normalize()) // !! valid non-zero binormal must be set because otherwise triangles can become black !!
  365. {
  366. if(vtx.nrm() && vtx.tan())bin=Cross(vtx.nrm(i), vtx.tan(i));else
  367. if(vtx.nrm() )bin=PerpN(vtx.nrm(i) );else
  368. if( vtx.tan())bin=PerpN( vtx.tan(i));else
  369. bin.set(0, -1, 0);
  370. }
  371. }
  372. }
  373. return T;
  374. }
  375. MeshBase& MeshBase::setAutoTanBin()
  376. {
  377. if(vtx.nrm())
  378. {
  379. setTangents(); if(vtx.tan())
  380. {
  381. setBinormals(); if(vtx.bin())
  382. {
  383. REPA(vtx)
  384. {
  385. Vec bin=Cross(vtx.nrm(i), vtx.tan(i));
  386. if(Dot(bin, vtx.bin(i))<0.99f)return T; // if binormals are different, then it means that binormal is necessary, so keep it and return without deleting it
  387. }
  388. exclude(VTX_BIN); // binormal unnecessary
  389. }
  390. }
  391. }else exclude(VTX_TAN_BIN);
  392. return T;
  393. }
  394. /******************************************************************************
  395. MeshBase& setSolid ( ); // fill 'edge.flag' EDGE_FLAG with solid info
  396. MeshBase& MeshBase::setSolid()
  397. {
  398. if(!edge.adj_face)setAdjacencies();
  399. if(!edge.flag )AllocZero (edge.flag, edge.num);
  400. Byte *flag=edge.flag;
  401. VecI2 *adj =edge.adj_face;
  402. REP(edge.num)
  403. {
  404. *flag&=~ETQ_LR;
  405. if(adj->c[0]!=-1)*flag|= ETQ_R;
  406. if(adj->c[1]!=-1)*flag|= ETQ_L;
  407. flag++;
  408. adj ++;
  409. }
  410. return T;
  411. }
  412. /******************************************************************************
  413. MeshBase& setID (Int solid, Int not_solid=-1 ); // set face ID values (edge.id, tri.id, quad.id) to 'solid' / 'not_solid'
  414. MeshBase& MeshBase::setID(Int solid, Int not_solid)
  415. {
  416. include(ID_ALL);
  417. ;
  418. VecI2 *eid =edge.id,
  419. *tid =tri .id,
  420. *qid =quad.id;
  421. if(C Byte *flag=edge.flag)
  422. {
  423. REPA(edge)
  424. {
  425. (eid++)->set(((*flag)&ETQ_R) ? solid : not_solid,
  426. ((*flag)&ETQ_L) ? solid : not_solid);
  427. flag++;
  428. }
  429. }else
  430. {
  431. REPA(edge)eid[i].set(not_solid);
  432. }
  433. REPA(tri )tid[i].set(solid, not_solid);
  434. REPA(quad)qid[i].set(solid, not_solid);
  435. return T;
  436. }
  437. /******************************************************************************/
  438. MeshBase& MeshBase::setVtxDup2D(UInt flag, Flt pos_eps, Flt nrm_cos)
  439. {
  440. include(VTX_DUP); // vtx dup doesn't need to be initialized here, because the algorithm works in a way that only processed vertexes are tested
  441. flag&=(T.flag()&(VTX_NRM_TAN_BIN|VTX_HLP|VTX_TEX_ALL|VTX_SIZE|VTX_SKIN|VTX_MATERIAL|VTX_COLOR|VTX_FLAG)); // only these are tested
  442. // link rect->vtx
  443. Rects rects (Rect(T) , vtxs());
  444. Index rect_vtx(rects.num(), vtxs());
  445. REPA(vtx)rect_vtx.elmGroup(rects.index(vtx.pos(i).xy), i); rect_vtx.set();
  446. // get duplicates
  447. Int xs=rects.cells.x,
  448. ys=rects.cells.y;
  449. FREPD(y, ys)
  450. FREPD(x, xs)
  451. {
  452. Int rect_tests=0;
  453. IndexGroup *rect_test[2+3], *rect_cur=&rect_vtx.group[x+y*xs];
  454. rect_test[rect_tests++]=rect_cur ;
  455. if(x)rect_test[rect_tests++]=rect_cur-1;
  456. if(y)
  457. {
  458. if(x<xs-1)rect_test[rect_tests++]=rect_cur+1-xs;
  459. rect_test[rect_tests++]=rect_cur -xs;
  460. if(x )rect_test[rect_tests++]=rect_cur-1-xs;
  461. }
  462. FREPA(*rect_cur)
  463. {
  464. Int num_cur=(*rect_cur)[i];
  465. Vec2 &pos_cur=vtx.pos(num_cur).xy;
  466. REPD(c, rect_tests)
  467. {
  468. IndexGroup *rt=rect_test[c];
  469. REPD(j, (rect_cur==rt) ? i : rt->num)
  470. {
  471. Int num_test=(*rt)[j]; if(vtx.dup(num_test)==num_test && Equal(pos_cur, vtx.pos(num_test).xy, pos_eps))
  472. {
  473. if(flag)
  474. {
  475. if(flag&VTX_NRM && Dot (vtx.nrm (num_cur), vtx.nrm (num_test))<nrm_cos )continue;
  476. if(flag&VTX_TAN && Dot (vtx.tan (num_cur), vtx.tan (num_test))<EPS_TAN_COS)continue;
  477. if(flag&VTX_BIN && Dot (vtx.bin (num_cur), vtx.bin (num_test))<EPS_TAN_COS)continue;
  478. if(flag&VTX_HLP && !Equal(vtx.hlp (num_cur), vtx.hlp (num_test)) )continue;
  479. if(flag&VTX_TEX0 && !Equal(vtx.tex0 (num_cur), vtx.tex0 (num_test)) )continue;
  480. if(flag&VTX_TEX1 && !Equal(vtx.tex1 (num_cur), vtx.tex1 (num_test)) )continue;
  481. if(flag&VTX_TEX2 && !Equal(vtx.tex2 (num_cur), vtx.tex2 (num_test)) )continue;
  482. if(flag&VTX_SIZE && !Equal(vtx.size (num_cur), vtx.size (num_test)) )continue;
  483. if(flag&VTX_BLEND && vtx.blend (num_cur)!=vtx.blend (num_test) )continue;
  484. if(flag&VTX_MATRIX && vtx.matrix (num_cur)!=vtx.matrix (num_test) )continue;
  485. if(flag&VTX_MATERIAL && vtx.material(num_cur)!=vtx.material(num_test) )continue;
  486. if(flag&VTX_COLOR && vtx.color (num_cur)!=vtx.color (num_test) )continue;
  487. if(flag&VTX_FLAG && vtx.flag (num_cur)!=vtx.flag (num_test) )continue;
  488. }
  489. vtx.dup(num_cur)=num_test; goto next;
  490. }
  491. }
  492. }
  493. vtx.dup(num_cur)=num_cur;
  494. next:;
  495. }
  496. }
  497. return T;
  498. }
  499. MeshBase& MeshBase::setVtxDup (UInt flag, Flt pos_eps, Flt nrm_cos ) {return setVtxDupEx(flag, pos_eps, nrm_cos);}
  500. MeshBase& MeshBase::setVtxDupEx(UInt flag, Flt pos_eps, Flt nrm_cos, Bool smooth_groups_in_vtx_material)
  501. {
  502. include(VTX_DUP); // vtx dup doesn't need to be initialized here, because the algorithm works in a way that only processed vertexes are tested
  503. UInt t_flag=T.flag();
  504. flag &=(t_flag&(VTX_NRM_TAN_BIN|VTX_HLP|VTX_TEX_ALL|VTX_SIZE|VTX_SKIN|VTX_MATERIAL|VTX_COLOR|VTX_FLAG)); // only these are tested
  505. smooth_groups_in_vtx_material&=FlagTest(t_flag, VTX_MATERIAL);
  506. // link box->vtx
  507. Boxes boxes (Box(T) , vtxs());
  508. Index box_vtx(boxes.num(), vtxs());
  509. REPA(vtx)box_vtx.elmGroup(boxes.index(vtx.pos(i)), i); box_vtx.set();
  510. // get duplicates
  511. Int xs=boxes.cells.x,
  512. ys=boxes.cells.y, xys=xs*ys;
  513. FREPD(z, boxes.cells.z)
  514. FREPD(y, boxes.cells.y)
  515. FREPD(x, boxes.cells.x)
  516. {
  517. Int box_tests=0;
  518. IndexGroup *box_test[2+3+9], *box_cur=&box_vtx.group[x+y*xs+z*xys];
  519. box_test[box_tests++]=box_cur ;
  520. if(x)box_test[box_tests++]=box_cur-1;
  521. if(y)
  522. {
  523. if(x<xs-1)box_test[box_tests++]=box_cur+1-xs;
  524. box_test[box_tests++]=box_cur -xs;
  525. if( x)box_test[box_tests++]=box_cur-1-xs;
  526. }
  527. if(z)
  528. {
  529. if(y<ys-1)
  530. {
  531. if(x<xs-1)box_test[box_tests++]=box_cur+1+xs-xys;
  532. box_test[box_tests++]=box_cur +xs-xys;
  533. if( x)box_test[box_tests++]=box_cur-1+xs-xys;
  534. }
  535. if(x<xs-1)box_test[box_tests++]=box_cur+1 -xys;
  536. box_test[box_tests++]=box_cur -xys;
  537. if( x)box_test[box_tests++]=box_cur-1 -xys;
  538. if(y)
  539. {
  540. if(x<xs-1)box_test[box_tests++]=box_cur+1-xs-xys;
  541. box_test[box_tests++]=box_cur -xs-xys;
  542. if( x)box_test[box_tests++]=box_cur-1-xs-xys;
  543. }
  544. }
  545. FREPA(*box_cur)
  546. {
  547. Int num_cur=(*box_cur)[i];
  548. Vec &pos_cur=vtx.pos(num_cur);
  549. REPD(c, box_tests)
  550. {
  551. IndexGroup *bt=box_test[c];
  552. REPD(j, (box_cur==bt) ? i : bt->num)
  553. {
  554. Int num_test=(*bt)[j]; if(vtx.dup(num_test)==num_test && Equal(pos_cur, vtx.pos(num_test), pos_eps))
  555. {
  556. if(flag)
  557. {
  558. if(flag&VTX_NRM && Dot (vtx.nrm (num_cur), vtx.nrm (num_test))<nrm_cos )continue;
  559. if(flag&VTX_TAN && Dot (vtx.tan (num_cur), vtx.tan (num_test))<EPS_TAN_COS)continue;
  560. if(flag&VTX_BIN && Dot (vtx.bin (num_cur), vtx.bin (num_test))<EPS_TAN_COS)continue;
  561. if(flag&VTX_HLP && !Equal(vtx.hlp (num_cur), vtx.hlp (num_test)) )continue;
  562. if(flag&VTX_TEX0 && !Equal(vtx.tex0 (num_cur), vtx.tex0 (num_test)) )continue;
  563. if(flag&VTX_TEX1 && !Equal(vtx.tex1 (num_cur), vtx.tex1 (num_test)) )continue;
  564. if(flag&VTX_TEX2 && !Equal(vtx.tex2 (num_cur), vtx.tex2 (num_test)) )continue;
  565. if(flag&VTX_SIZE && !Equal(vtx.size (num_cur), vtx.size (num_test)) )continue;
  566. if(flag&VTX_BLEND && vtx.blend (num_cur)!=vtx.blend (num_test) )continue;
  567. if(flag&VTX_MATRIX && vtx.matrix (num_cur)!=vtx.matrix (num_test) )continue;
  568. if(flag&VTX_MATERIAL && vtx.material(num_cur)!=vtx.material(num_test) )continue;
  569. if(flag&VTX_COLOR && vtx.color (num_cur)!=vtx.color (num_test) )continue;
  570. if(flag&VTX_FLAG && vtx.flag (num_cur)!=vtx.flag (num_test) )continue;
  571. }
  572. if(smooth_groups_in_vtx_material)if(!(vtx.material(num_cur).u&vtx.material(num_test).u))continue; // if there are no shared smooth groups
  573. vtx.dup(num_cur)=num_test; goto next;
  574. }
  575. }
  576. }
  577. vtx.dup(num_cur)=num_cur;
  578. next:;
  579. }
  580. }
  581. return T;
  582. }
  583. /******************************************************************************/
  584. struct EdgeAdj
  585. {
  586. VecI2 ind, adj_face;
  587. EdgeAdj& set(Int p0, Int p1, Int f0, Int f1) {ind.set(p0, p1); adj_face.set(f0, f1); return T;}
  588. };
  589. struct Adj
  590. {
  591. Int face, // face index
  592. vtxi, // index of vertex place in the face
  593. face_extra_vtx; // index of vertex which is loose
  594. void set(Int face, Int vtxi, Int face_extra_vtx) {T.face=face; T.vtxi=vtxi; T.face_extra_vtx=face_extra_vtx;}
  595. };
  596. MeshBase& MeshBase::setAdjacencies(Bool faces, Bool edges)
  597. {
  598. if(faces || edges)
  599. {
  600. include((faces ? FACE_ADJ_FACE : 0)|(edges ? FACE_ADJ_EDGE : 0));
  601. if(faces)
  602. {
  603. SetMemN(tri .adjFace(), 0xFF, tris ());
  604. SetMemN(quad.adjFace(), 0xFF, quads());
  605. }
  606. if(edges)
  607. {
  608. SetMemN(tri .adjEdge(), 0xFF, tris ());
  609. SetMemN(quad.adjEdge(), 0xFF, quads());
  610. }
  611. // link vtx->face
  612. Index vtx_face; linkVtxFace(vtx_face);
  613. // add double sided edges
  614. Memb<EdgeAdj> _edge(1024);
  615. #if 1 // new version, that generates duplicates of edges
  616. REPAD(f0, tri) // for each triangle
  617. {
  618. VecI f0i=tri.ind(f0); f0i.remap(vtx.dup());
  619. REPD(f0vi, 3) // for each triangle vertex
  620. {
  621. Int f0v0=f0i.c[ f0vi ],
  622. f0v1=f0i.c[(f0vi+1)%3];
  623. IndexGroup &ig=vtx_face.group[f0v0];
  624. REPAD(vfi, ig) // for each face that the vertex belongs to
  625. {
  626. Int f1=ig[vfi]; VecI4 f1i; Int f1vtxs;
  627. if( f1&SIGN_BIT) // quad
  628. {
  629. f1i=quad.ind(f1^SIGN_BIT); f1i.remap(vtx.dup()); f1vtxs=4;
  630. }else
  631. {
  632. if(f1>=f0)continue; // if the other triangle has a greater index (or is the same one) then skip, because we will check this again later for the other triangle
  633. f1i.xyz=tri.ind(f1); f1i.xyz.remap(vtx.dup()); f1vtxs=3;
  634. }
  635. REPD(f1vi, f1vtxs) // for each face vertex
  636. if(f0v1==f1i.c[ f1vi ] // here f0v1==f1v0 (order of vertexes is swapped)
  637. && f0v0==f1i.c[(f1vi+1)%f1vtxs]) // here f0v0==f1v1
  638. {
  639. if(faces){tri.adjFace(f0).c[f0vi]=f1 ; ((f1&SIGN_BIT) ? quad.adjFace(f1^SIGN_BIT).c[f1vi] : tri.adjFace(f1).c[f1vi])=f0;}
  640. if(edges){tri.adjEdge(f0).c[f0vi]=_edge.elms(); ((f1&SIGN_BIT) ? quad.adjEdge(f1^SIGN_BIT).c[f1vi] : tri.adjEdge(f1).c[f1vi])=_edge.elms(); _edge.New().set(f0v0, f0v1, f0, f1);}
  641. break;
  642. }
  643. }
  644. }
  645. }
  646. REPAD(f0, quad) // for each quad
  647. {
  648. VecI4 f0i=quad.ind(f0); f0i.remap(vtx.dup());
  649. REPD(f0vi, 4) // for each quad vertex
  650. {
  651. Int f0v0=f0i.c[ f0vi ],
  652. f0v1=f0i.c[(f0vi+1)%4];
  653. IndexGroup &ig=vtx_face.group[f0v0];
  654. REPAD(vfi, ig) // for each face that the vertex belongs to
  655. {
  656. // in this case we will process only quads, as we've already processed triangle-quad pairs above
  657. Int f1=ig[vfi];
  658. if( f1&SIGN_BIT) // quad
  659. {
  660. f1^=SIGN_BIT;
  661. if(f1<f0) // here process only quads that have index smaller than 'f0', because we will check this again later for the other quad
  662. {
  663. VecI4 f1i=quad.ind(f1); f1i.remap(vtx.dup());
  664. REPD(f1vi, 4) // for each quad vertex
  665. if(f0v1==f1i.c[ f1vi ] // here f0v1==f1v0 (order of vertexes is swapped)
  666. && f0v0==f1i.c[(f1vi+1)%4]) // here f0v0==f1v1
  667. {
  668. if(faces){quad.adjFace(f0).c[f0vi]=f1^SIGN_BIT ; quad.adjFace(f1).c[f1vi]=f0^SIGN_BIT;}
  669. if(edges){quad.adjEdge(f0).c[f0vi]=_edge.elms(); quad.adjEdge(f1).c[f1vi]=_edge.elms(); _edge.New().set(f0v0, f0v1, f0^SIGN_BIT, f1^SIGN_BIT);}
  670. break;
  671. }
  672. }
  673. }
  674. }
  675. }
  676. }
  677. #else
  678. this version may crash the 'DirectX::OptimizeFaces'
  679. Memt<Adj> adj;
  680. REPAD(f0, tri) // for each triangle
  681. {
  682. VecI f0i=tri.ind(f0); f0i.remap(vtx.dup());
  683. REPD(f0vi, 3) // for each triangle vertexes
  684. {
  685. Int f0v0=f0i.c[ f0vi ],
  686. f0v1=f0i.c[(f0vi+1)%3];
  687. IndexGroup &ig=vtx_face.group[f0v0];
  688. REPAD(vfi, ig) // for each face that the vertex belongs to
  689. {
  690. Int f1=ig[vfi];
  691. if( f1&SIGN_BIT) // quad
  692. {
  693. VecI4 f1i=quad.ind(f1^SIGN_BIT); f1i.remap(vtx.dup());
  694. if(f1i.c[0]==f0v1 && f1i.c[1]==f0v0)adj.New().set(f1, 0, f1i.c[2]);else
  695. if(f1i.c[1]==f0v1 && f1i.c[2]==f0v0)adj.New().set(f1, 1, f1i.c[3]);else
  696. if(f1i.c[2]==f0v1 && f1i.c[3]==f0v0)adj.New().set(f1, 2, f1i.c[0]);else
  697. if(f1i.c[3]==f0v1 && f1i.c[0]==f0v0)adj.New().set(f1, 3, f1i.c[1]);
  698. }else
  699. {
  700. VecI f1i=tri.ind(f1); f1i.remap(vtx.dup());
  701. if(f1i.c[0]==f0v1 && f1i.c[1]==f0v0)adj.New().set(f1, 0, f1i.c[2]);else
  702. if(f1i.c[1]==f0v1 && f1i.c[2]==f0v0)adj.New().set(f1, 1, f1i.c[0]);else
  703. if(f1i.c[2]==f0v1 && f1i.c[0]==f0v0)adj.New().set(f1, 2, f1i.c[1]);
  704. }
  705. }
  706. if(adj.elms())
  707. {
  708. if(adj.elms()>1 && vtx.pos()) // if the edge links many faces (for example 3 faces like "T")
  709. {
  710. Matrix m; m.setPosDir(vtx.pos(f0v0), !(vtx.pos(f0v1)-vtx.pos(f0v0)));
  711. Flt angle, a0=AngleFast(vtx.pos(f0i.c[(f0vi+2)%3]), m);
  712. Int max=-1; REPA(adj)
  713. {
  714. Flt a=AngleFast(vtx.pos(adj[i].face_extra_vtx), m);
  715. if( a<a0)a+=PI2;
  716. if(max<0 || a>angle){max=i; angle=a;}
  717. }
  718. adj[0]=adj[max];
  719. }
  720. Adj &a =adj[0];
  721. Int f1 =a.face,
  722. f1vi=a.vtxi;
  723. if( f1&SIGN_BIT || f1>f0)
  724. {
  725. if(faces){tri.adjFace(f0).c[f0vi]=f1 ; ((f1&SIGN_BIT) ? quad.adjFace(f1^SIGN_BIT).c[f1vi] : tri.adjFace(f1).c[f1vi])=f0;}
  726. if(edges){tri.adjEdge(f0).c[f0vi]=_edge.elms(); ((f1&SIGN_BIT) ? quad.adjEdge(f1^SIGN_BIT).c[f1vi] : tri.adjEdge(f1).c[f1vi])=_edge.elms(); _edge.New().set(f0v0, f0v1, f0, f1);}
  727. }
  728. adj.clear();
  729. }
  730. }
  731. }
  732. REPAD(f0, quad) // quads
  733. {
  734. VecI4 f0i=quad.ind(f0); f0i.remap(vtx.dup());
  735. REPD(f0vi, 4)
  736. {
  737. Int f0v0=f0i.c[ f0vi ],
  738. f0v1=f0i.c[(f0vi+1)%4];
  739. IndexGroup &ig=vtx_face.group[f0v0];
  740. REPAD(vfi, ig)
  741. {
  742. Int f1=ig[vfi];
  743. if( f1&SIGN_BIT) // quad
  744. {
  745. VecI4 f1i=quad.ind(f1^SIGN_BIT); f1i.remap(vtx.dup());
  746. if(f1i.c[0]==f0v1 && f1i.c[1]==f0v0)adj.New().set(f1, 0, f1i.c[2]);else
  747. if(f1i.c[1]==f0v1 && f1i.c[2]==f0v0)adj.New().set(f1, 1, f1i.c[3]);else
  748. if(f1i.c[2]==f0v1 && f1i.c[3]==f0v0)adj.New().set(f1, 2, f1i.c[0]);else
  749. if(f1i.c[3]==f0v1 && f1i.c[0]==f0v0)adj.New().set(f1, 3, f1i.c[1]);
  750. }else
  751. {
  752. VecI f1i=tri.ind(f1); f1i.remap(vtx.dup());
  753. if(f1i.c[0]==f0v1 && f1i.c[1]==f0v0)adj.New().set(f1, 0, f1i.c[2]);else
  754. if(f1i.c[1]==f0v1 && f1i.c[2]==f0v0)adj.New().set(f1, 1, f1i.c[0]);else
  755. if(f1i.c[2]==f0v1 && f1i.c[0]==f0v0)adj.New().set(f1, 2, f1i.c[1]);
  756. }
  757. }
  758. if(adj.elms())
  759. {
  760. if(adj.elms()>1 && vtx.pos()) // if the edge links many faces (for example 3 faces like "T")
  761. {
  762. Matrix m; m.setPosDir(vtx.pos(f0v0), !(vtx.pos(f0v1)-vtx.pos(f0v0)));
  763. Flt angle, a0=AngleFast(vtx.pos(f0i.c[(f0vi+2)%4]), m);
  764. Int max=-1; REPA(adj)
  765. {
  766. Flt a=AngleFast(vtx.pos(adj[i].face_extra_vtx), m);
  767. if(a<a0)a+=PI2;
  768. if(max<0 || a>angle){max=i; angle=a;}
  769. }
  770. adj[0]=adj[max];
  771. }
  772. Adj &a =adj[0];
  773. Int f1 =a.face,
  774. f1vi=a.vtxi;
  775. if((f1&SIGN_BIT) && (f1^SIGN_BIT)>f0)
  776. {
  777. if(faces){quad.adjFace(f0).c[f0vi]=f1 ; quad.adjFace(f1^SIGN_BIT).c[f1vi]=f0^SIGN_BIT;}
  778. if(edges){quad.adjEdge(f0).c[f0vi]=_edge.elms(); quad.adjEdge(f1^SIGN_BIT).c[f1vi]=_edge.elms(); _edge.New().set(f0v0, f0v1, f0^SIGN_BIT, f1);}
  779. }
  780. adj.clear();
  781. }
  782. }
  783. }
  784. #endif
  785. if(edges)
  786. {
  787. // add one sided edges
  788. FREPA(tri)
  789. {
  790. Int *p=tri.adjEdge(i).c;
  791. REPD(j, 3)if(p[j]<0)
  792. {
  793. Int *v=tri.ind(i).c;
  794. p[j]=_edge.elms();
  795. _edge.New().set(v[j], v[(j+1)%3], i, -1).ind.remap(vtx.dup());
  796. }
  797. }
  798. FREPA(quad)
  799. {
  800. Int *p=quad.adjEdge(i).c;
  801. REPD(j, 4)if(p[j]<0)
  802. {
  803. Int *v=quad.ind(i).c;
  804. p[j]=_edge.elms();
  805. _edge.New().set(v[j], v[(j+1)%4], i^SIGN_BIT, -1).ind.remap(vtx.dup());
  806. }
  807. }
  808. // set edges
  809. exclude(EDGE_ALL); edge._elms=_edge.elms();
  810. include(EDGE_IND|EDGE_ADJ_FACE);
  811. FREPA(edge)
  812. {
  813. edge.ind (i)=_edge[i].ind;
  814. edge.adjFace(i)=_edge[i].adj_face;
  815. }
  816. }
  817. }
  818. return T;
  819. }
  820. /******************************************************************************/
  821. struct MeshAO
  822. {
  823. static Flt Full (Flt x) {return 0 ;}
  824. static Flt Quartic(Flt x) {return Sqr(Sqr(x));}
  825. static Flt Square (Flt x) {return Sqr(x) ;}
  826. static Flt Linear (Flt x) {return x ;}
  827. static Flt LinearR(Flt x) {return 2-2/(x+1);}
  828. static Flt SquareR(Flt x) {return 1-Sqr(1-x);}
  829. C Vec *pos, *nrm;
  830. Color *col;
  831. Memt<Vec> ray_dir;
  832. Byte max;
  833. Flt mul, add, ray_length, pos_eps;
  834. PhysPart body;
  835. Flt (*func)(Flt x);
  836. INLINE Bool sweep(C Vec &pos, C Vec &move, Flt *frac)
  837. {
  838. #if 0
  839. return Sweep(pos, move, *mesh, null, frac, null, null, true, two_sided);
  840. #else
  841. PhysHitBasic hit;
  842. if(body.ray(pos, move, null, frac ? &hit : null, true))
  843. {
  844. if(frac)*frac=hit.frac;
  845. return true;
  846. }
  847. return false;
  848. #endif
  849. }
  850. static void Set(IntPtr elm_index, MeshAO &ao, Int thread_index) {ao.set(elm_index);}
  851. void set(Int vtx)
  852. {
  853. C Vec &pos=T.pos[vtx], &nrm=T.nrm[vtx];
  854. Flt light=0;
  855. REPA(ray_dir)
  856. {
  857. C Vec &ray=ray_dir[i];
  858. Flt d=Dot(nrm, ray); if(d>0)
  859. {
  860. Flt frac; if(sweep(pos+ray*pos_eps, ray, &frac))light+=func(frac)*d;else light+=d;
  861. }
  862. }
  863. Color &c=col[vtx]; c.r=c.g=c.b=Mid(RoundPos(light*mul+add), max, 255); // keep alpha
  864. }
  865. void process(Int vtxs, Threads *threads)
  866. {
  867. if(threads)threads->process1(vtxs, Set, T);else REP(vtxs)set(i);
  868. }
  869. MeshAO(Flt strength, Flt bias, Flt max, Flt ray_length, Flt pos_eps, Int rays, MESH_AO_FUNC func)
  870. {
  871. switch(func)
  872. {
  873. default :
  874. case MAF_FULL : T.func=Full ; break;
  875. case MAF_QUARTIC : T.func=Quartic; break;
  876. case MAF_SQUARE : T.func=Square ; break;
  877. case MAF_LINEAR : T.func=Linear ; break;
  878. case MAF_LINEAR_REV: T.func=LinearR; break;
  879. case MAF_SQUARE_REV: T.func=SquareR; break;
  880. }
  881. T.ray_length =Max(0, ray_length);
  882. T.pos_eps =Mid(pos_eps, 0.0f, T.ray_length*0.5f);
  883. T.ray_length-=T.pos_eps;
  884. if(T.ray_length)T.pos_eps /=T.ray_length; // because we pre-multiply 'ray_dir' with 'ray_length' then we need to adjust 'pos_eps'
  885. T.max =FltToByte(1-max);
  886. Int rays_res=Max(1, Round(Sqrt(rays/6.0f))); // rays resolution in 2D, in one of 6 cube faces
  887. rays=Sqr(rays_res)*6; // total number of rays
  888. ray_dir.setNum(rays);
  889. Int r=0, r_pos=0;
  890. Flt ray_step=PI_2/rays_res;
  891. Vec ray_base; ray_base.z=1;
  892. Dbl ray_sum=0;
  893. REPD(x, rays_res)
  894. {
  895. ray_base.x=Tan(x*ray_step-PI_4);
  896. REPD(y, rays_res)
  897. {
  898. ray_base.y=Tan(y*ray_step-PI_4);
  899. Vec n=ray_base; n.normalize(); // normalized
  900. REPD(f, 6) // 6 cube faces
  901. {
  902. Vec ray; switch(f)
  903. {
  904. case 0: ray.set( n.x, n.y, n.z); break;
  905. case 1: ray.set(-n.z, n.y, n.x); break;
  906. case 2: ray.set(-n.x, -n.y, -n.z); break;
  907. case 3: ray.set( n.z, -n.y, -n.x); break;
  908. case 4: ray.set( n.x, n.z, -n.y); break;
  909. case 5: ray.set(-n.x, -n.z, n.y); break;
  910. }
  911. ray*=T.ray_length; // pre-multiply so we don't have to do this for each vertex*ray
  912. ray_dir[r++]=ray;
  913. if(ray.x>0){r_pos++; ray_sum+=ray.x;} // Dot(ray, Vec(1, 0, 0))
  914. }
  915. }
  916. }
  917. add=255*(1-strength + strength*bias);
  918. mul=255* strength/ray_sum;
  919. //mul=255* strength/r_pos ; // this is for light independent on the Dot product
  920. }
  921. };
  922. /******************************************************************************/
  923. MeshBase& MeshBase::setVtxAO(Flt strength, Flt bias, Flt max, Flt ray_length, Flt pos_eps, Int rays, MESH_AO_FUNC func, Threads *threads)
  924. {
  925. if(vtx.pos() && vtx.nrm())
  926. {
  927. MeshAO ao(strength, bias, max, ray_length, pos_eps, rays, func);
  928. if(ao.body.createMeshTry(T))
  929. {
  930. if(!vtx.color()){include(VTX_COLOR); REPA(vtx)vtx.color(i)=WHITE;} // setup colors, especially needed for Alpha which is kept and not overwritten, but set all components in case some codes below don't get executed
  931. if(ao.pos=vtx.pos ())
  932. if(ao.nrm=vtx.nrm ())
  933. if(ao.col=vtx.color())ao.process(vtxs(), threads);
  934. }
  935. }
  936. return T;
  937. }
  938. MeshLod& MeshLod::setVtxAO(Flt strength, Flt bias, Flt max, Flt ray_length, Flt pos_eps, Int rays, MESH_AO_FUNC func, Threads *threads)
  939. {
  940. if(parts.elms())
  941. {
  942. MeshAO ao(strength, bias, max, ray_length, pos_eps, rays, func);
  943. if(ao.body.createMeshTry(T, false, true))REPA(T)
  944. {
  945. MeshPart &part=parts[i];
  946. MeshBase &base=part.base;
  947. if(!base.vtx.color()){base.include(VTX_COLOR); REPA(base.vtx)base.vtx.color(i)=WHITE;} // setup colors, especially needed for Alpha which is kept and not overwritten, but set all components in case some codes below don't get executed
  948. if(ao.pos=base.vtx.pos ())
  949. if(ao.nrm=base.vtx.nrm ())
  950. if(ao.col=base.vtx.color())ao.process(base.vtxs(), threads);
  951. }
  952. }
  953. return T;
  954. }
  955. /******************************************************************************/
  956. }
  957. /******************************************************************************/