Mshb Convert.cpp 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. namespace EE{
  4. /******************************************************************************/
  5. // INFLATE EDGES
  6. /******************************************************************************/
  7. struct EdgeTex
  8. {
  9. Edge edge;
  10. Vec2 tex[2];
  11. Color col[2];
  12. void set(C Vec &p0, C Vec &p1, C Vec2 &t0, C Vec2 &t1, C Color &c0, C Color &c1) {edge.set(p0,p1); tex[0]=t0; tex[1]=t1; col[0]=c0; col[1]=c1;}
  13. };
  14. struct TriTex
  15. {
  16. Tri tri;
  17. Vec2 tex[3];
  18. Color col[3];
  19. void set(Vec &p0, Vec &p1, Vec &p2, Vec2 &t0, Vec2 &t1, Vec2 &t2, C Color &c0, C Color &c1, C Color &c2) {tri.set(p0, p1, p2); tex[0]=t0; tex[1]=t1; tex[2]=t2; col[0]=c0; col[1]=c1; col[2]=c2;}
  20. };
  21. struct QuadTex
  22. {
  23. Quad quad;
  24. Vec2 tex[4];
  25. Color col[4];
  26. void set(Vec &p0, Vec &p1, Vec &p2, Vec &p3, Vec2 &t0, Vec2 &t1, Vec2 &t2, Vec2 &t3, C Color &c0, C Color &c1, C Color &c2, C Color &c3) {quad.set(p0, p1, p2, p3); tex[0]=t0; tex[1]=t1; tex[2]=t2; tex[3]=t3; col[0]=c0; col[1]=c1; col[2]=c2; col[3]=c3;}
  27. };
  28. MeshBase& MeshBase::inflateEdges(TEX_MODE x_tex_coords, TEX_MODE y_tex_coords, Bool to_edges) // assumes that vertexes are welded, weldVtx
  29. {
  30. Bool adjust_length=true;
  31. Index vtx_vtx, vtx_edge;
  32. Memc<EdgeTex> fat_edge;
  33. Memc<TriTex > fat_tri ;
  34. Memc<QuadTex> fat_quad;
  35. Bool *tex_set=null;
  36. Flt *tex_y =null,
  37. *size =vtx.size();
  38. Vec *pos =vtx.pos ();
  39. linkVtxVtxOnEdge(vtx_vtx, true);
  40. if(y_tex_coords!=TEX_NONE && y_tex_coords!=TEX_KEEP)
  41. {
  42. linkVtxEdge(vtx_edge, false);
  43. AllocZero(tex_set, vtxs());
  44. Alloc (tex_y , vtxs());
  45. Memc<Int> vtx_left;
  46. FREPA(vtx)if(!tex_set[i]) // iterate all not yet set vertexes (in case there are multiple sets not joined together)
  47. {
  48. vtx_left.New()=i;
  49. tex_set[i]=true;
  50. tex_y [i]=0;
  51. for(; vtx_left.elms(); ) // fire the "recursive" loop
  52. {
  53. Int v =vtx_left.pop ( ); // take vertex
  54. IndexGroup &ig=vtx_edge.group[v];
  55. REPA(ig) // iterate all its edges, and find a vertex which hasn't been set yet
  56. {
  57. Int e =ig[i];
  58. VecI2 &ind=edge.ind(e);
  59. Int v2 =-1, dir;
  60. if(!tex_set[ind.y]){v2=ind.y; dir= 1;}else
  61. if(!tex_set[ind.x]){v2=ind.x; dir=-1;}
  62. if(v2>=0)
  63. {
  64. Flt dist=Dist(pos[v], pos[v2]);
  65. if( dist)
  66. {
  67. Flt old_z=pos[v ].z,
  68. new_z=pos[v2].z;
  69. if( new_z<old_z) // only if flowing downwards (falling)
  70. {
  71. Flt dist_z=Abs(old_z-new_z), // if most of the distance is vertical (here described by Z) then increase the "speed of river" (by reducing the difference between texture coordinates)
  72. frac =dist_z/dist;
  73. dist*=Lerp(0.1f, 1.0f, Sqr(1-frac));
  74. }
  75. }
  76. tex_set[v2]=true;
  77. tex_y [v2]=tex_y[v]+dist*dir; // set tex coords as equal to previous vertex + distance between them
  78. vtx_left.add(v2);
  79. }
  80. }
  81. }
  82. }
  83. if(y_tex_coords==TEX_UNIFORM)
  84. {
  85. Flt min, max; MinMax(tex_y, vtxs(), min, max);
  86. Flt scale=max-min; if(scale)scale=1.0f/scale; Flt add=-min*scale;
  87. REP(vtxs())tex_y[i]=tex_y[i]*scale+add;
  88. }
  89. }
  90. REPAD(e, edge)
  91. {
  92. VecI2 &ind=edge.ind(e);
  93. Int p0 =ind.x,
  94. p1 =ind.y;
  95. // we're going from p0 to p1
  96. Flt size0=(size ? size[p0] : 1),
  97. size1=(size ? size[p1] : 1);
  98. Vec pos0 =pos[p0],
  99. pos1 =pos[p1];
  100. Vec2 right=PerpN(pos1.xy-pos0.xy);
  101. // find a pair of vertexes for p0
  102. Int p0_p=-1, p0_n=-1; // previous, next
  103. {
  104. IndexGroup &ig=vtx_vtx.group[p0];
  105. if(ig.num>1) // if vertex is connected with at least 2 others
  106. REPA(ig)if(ig.elm[i]==p1)
  107. {
  108. p0_p=ig.elm[(i+ig.num-1)%ig.num];
  109. p0_n=ig.elm[(i+ 1)%ig.num];
  110. break;
  111. }
  112. }
  113. // find a pair of vertexes for p1
  114. Int p1_p=-1, p1_n=-1; // previous, next
  115. {
  116. IndexGroup &ig=vtx_vtx.group[p1];
  117. if(ig.num>1) // if vertex is connected with at least 2 others
  118. REPA(ig)if(ig.elm[i]==p0)
  119. {
  120. p1_p=ig.elm[(i+ig.num-1)%ig.num];
  121. p1_n=ig.elm[(i+ 1)%ig.num];
  122. break;
  123. }
  124. }
  125. Vec lb, rb, lf, rf; // pos
  126. Vec2 tlb, trb, tlf, trf; // tex
  127. Color cb, cf ; // col
  128. Flt max_div=SQRT2_2;
  129. if(vtx.color())
  130. {
  131. cb=vtx.color(p0);
  132. cf=vtx.color(p1);
  133. }
  134. // lb
  135. {
  136. Vec2 n=-right;
  137. Flt s= size0;
  138. if(p0_n>=0)
  139. {
  140. Vec2 nn =PerpN(pos[p0_n].xy-pos0.xy);
  141. Flt angle=AngleFull(PI-AngleBetween(n, nn));
  142. n+=nn;
  143. n.normalize();
  144. if(adjust_length)s/=Max(max_div, Sin(angle/2));
  145. }
  146. n*=s;
  147. lb=pos0+n.xy0();
  148. switch(x_tex_coords)
  149. {
  150. default : tlb.x= 0; break;
  151. case TEX_KEEP : tlb.x=(vtx.tex0() ? vtx.tex0(p0).x : 0); break;
  152. case TEX_UNIFORM: tlb.x= 0; break;
  153. case TEX_SCALED : tlb.x=-s; break;
  154. }
  155. switch(y_tex_coords)
  156. {
  157. default : tlb.y=0; break;
  158. case TEX_KEEP : tlb.y=(vtx.tex0() ? vtx.tex0(p0).y : 0); break;
  159. case TEX_UNIFORM:
  160. case TEX_SCALED : tlb.y=tex_y[p0]; break;
  161. }
  162. }
  163. // rb
  164. {
  165. Vec2 n=right;
  166. Flt s=size0;
  167. if(p0_p>=0)
  168. {
  169. Vec2 nn =PerpN(pos0.xy-pos[p0_p].xy);
  170. Flt angle=AngleFull(PI-AngleBetween(n, nn));
  171. n+=nn;
  172. n.normalize();
  173. if(adjust_length)s/=Max(max_div, Sin(angle/2));
  174. }
  175. n*=s;
  176. rb=pos0+n.xy0();
  177. switch(x_tex_coords)
  178. {
  179. default : trb.x=0; break;
  180. case TEX_KEEP : trb.x=(vtx.tex0() ? vtx.tex0(p0).x : 0); break;
  181. case TEX_UNIFORM: trb.x=1; break;
  182. case TEX_SCALED : trb.x=s; break;
  183. }
  184. switch(y_tex_coords)
  185. {
  186. default : trb.y=0; break;
  187. case TEX_KEEP : trb.y=(vtx.tex0() ? vtx.tex0(p0).y : 0); break;
  188. case TEX_UNIFORM:
  189. case TEX_SCALED : trb.y=tex_y[p0]; break;
  190. }
  191. }
  192. // lf
  193. {
  194. Vec2 n=-right;
  195. Flt s= size1;
  196. if(p1_p>=0)
  197. {
  198. Vec2 nn =PerpN(pos1.xy-pos[p1_p].xy);
  199. Flt angle=AngleFull(PI-AngleBetween(n, nn));
  200. n+=nn;
  201. n.normalize();
  202. if(adjust_length)s/=Max(max_div, Sin(angle/2));
  203. }
  204. n*=s;
  205. lf=pos1+n.xy0();
  206. switch(x_tex_coords)
  207. {
  208. default : tlf.x= 0; break;
  209. case TEX_KEEP : tlf.x=(vtx.tex0() ? vtx.tex0(p1).x : 0); break;
  210. case TEX_UNIFORM: tlf.x= 0; break;
  211. case TEX_SCALED : tlf.x=-s; break;
  212. }
  213. switch(y_tex_coords)
  214. {
  215. default : tlf.y=0; break;
  216. case TEX_KEEP : tlf.y=(vtx.tex0() ? vtx.tex0(p1).y : 0); break;
  217. case TEX_UNIFORM:
  218. case TEX_SCALED : tlf.y=tex_y[p1]; break;
  219. }
  220. }
  221. // rf
  222. {
  223. Vec2 n=right;
  224. Flt s=size1;
  225. if(p1_n>=0)
  226. {
  227. Vec2 nn =PerpN(pos[p1_n].xy-pos1.xy);
  228. Flt angle=AngleFull(PI-AngleBetween(n, nn));
  229. n+=nn;
  230. n.normalize();
  231. if(adjust_length)s/=Max(max_div, Sin(angle/2));
  232. }
  233. n*=s;
  234. rf=pos1+n.xy0();
  235. switch(x_tex_coords)
  236. {
  237. default : trf.x=0; break;
  238. case TEX_KEEP : trf.x=(vtx.tex0() ? vtx.tex0(p1).x : 0); break;
  239. case TEX_UNIFORM: trf.x=1; break;
  240. case TEX_SCALED : trf.x=s; break;
  241. }
  242. switch(y_tex_coords)
  243. {
  244. default : trf.y=0; break;
  245. case TEX_KEEP : trf.y=(vtx.tex0() ? vtx.tex0(p1).y : 0); break;
  246. case TEX_UNIFORM:
  247. case TEX_SCALED : trf.y=tex_y[p1]; break;
  248. }
  249. }
  250. if(to_edges)
  251. {
  252. fat_edge.New().set(lb, lf, tlb, tlf, cb, cf); // left edge
  253. fat_edge.New().set(rf, rb, trf, trb, cf, cb); // right edge
  254. if(p0_p<0 && p0_n<0)fat_edge.New().set(rb, lb, trb, tlb, cb, cb); // upper edge
  255. if(p1_p<0 && p1_n<0)fat_edge.New().set(lf, rf, tlf, trf, cf, cf); // lower edge
  256. }else
  257. {
  258. if(p0_p>=0 && p0_n>=0 && p0_p!=p0_n)
  259. {
  260. Vec2 tb=Avg(tlb, trb);
  261. if(y_tex_coords==TEX_SCALED)
  262. {
  263. Flt d=Dist(Avg(lb, rb), pos0);
  264. tb.y=tex_y[p0]-d;
  265. }
  266. fat_tri.New().set(lb, rb, pos0, tlb, trb, tb, cb, cb, cb);
  267. }
  268. if(p1_p>=0 && p1_n>=0 && p1_p!=p1_n)
  269. {
  270. Vec2 tf=Avg(tlf, trf);
  271. if(y_tex_coords==TEX_SCALED)
  272. {
  273. Flt d=Dist(Avg(lf, rf), pos1);
  274. tf.y=tex_y[p1]+d;
  275. }
  276. fat_tri.New().set(rf, lf, pos1, trf, tlf, tf, cf, cf, cf);
  277. }
  278. fat_quad.New().set(lb, lf, rf, rb, tlb, tlf, trf, trb, cb, cf, cf, cb);
  279. }
  280. }
  281. Bool set_tex_coords=(x_tex_coords==TEX_UNIFORM || x_tex_coords==TEX_SCALED
  282. || y_tex_coords==TEX_UNIFORM || y_tex_coords==TEX_SCALED
  283. || ((x_tex_coords==TEX_KEEP || y_tex_coords==TEX_KEEP) && vtx.tex0())
  284. );
  285. if(to_edges) // create from edges
  286. {
  287. create(fat_edge.elms()*2, fat_edge.elms(), 0, 0, EDGE_FLAG | (set_tex_coords ? VTX_TEX0 : 0) | (vtx.color() ? VTX_COLOR : 0));
  288. REPA(fat_edge)
  289. {
  290. if(vtx.tex0())
  291. {
  292. vtx.tex0(i*2+0)=fat_edge[i].tex[0];
  293. vtx.tex0(i*2+1)=fat_edge[i].tex[1];
  294. }
  295. if(vtx.color())
  296. {
  297. vtx.color(i*2+0)=fat_edge[i].col[0];
  298. vtx.color(i*2+1)=fat_edge[i].col[1];
  299. }
  300. vtx .pos (i*2+0)=fat_edge[i].edge.p[0];
  301. vtx .pos (i*2+1)=fat_edge[i].edge.p[1];
  302. edge.ind (i).set(i*2+0, i*2+1);
  303. edge.flag(i)=ETQ_R;
  304. }
  305. }else // create from faces
  306. {
  307. create(fat_tri.elms()*3+fat_quad.elms()*4, 0, fat_tri.elms(), fat_quad.elms(), (set_tex_coords ? VTX_TEX0 : 0) | (vtx.color() ? VTX_COLOR : 0));
  308. Int ofs=0;
  309. FREPA(fat_tri)
  310. {
  311. TriTex &t=fat_tri[i];
  312. if(vtx.tex0())
  313. {
  314. vtx.tex0(ofs+0)=t.tex[0];
  315. vtx.tex0(ofs+1)=t.tex[1];
  316. vtx.tex0(ofs+2)=t.tex[2];
  317. }
  318. if(vtx.color())
  319. {
  320. vtx.color(ofs+0)=t.col[0];
  321. vtx.color(ofs+1)=t.col[1];
  322. vtx.color(ofs+2)=t.col[2];
  323. }
  324. vtx.pos(ofs+0)=t.tri.p[0];
  325. vtx.pos(ofs+1)=t.tri.p[1];
  326. vtx.pos(ofs+2)=t.tri.p[2];
  327. tri.ind(i).set(ofs+0, ofs+1, ofs+2);
  328. ofs+=3;
  329. }
  330. FREPA(fat_quad)
  331. {
  332. QuadTex &q=fat_quad[i];
  333. if(vtx.tex0())
  334. {
  335. vtx.tex0(ofs+0)=q.tex[0];
  336. vtx.tex0(ofs+1)=q.tex[1];
  337. vtx.tex0(ofs+2)=q.tex[2];
  338. vtx.tex0(ofs+3)=q.tex[3];
  339. }
  340. if(vtx.color())
  341. {
  342. vtx.color(ofs+0)=q.col[0];
  343. vtx.color(ofs+1)=q.col[1];
  344. vtx.color(ofs+2)=q.col[2];
  345. vtx.color(ofs+3)=q.col[3];
  346. }
  347. vtx .pos(ofs+0)=q.quad.p[0];
  348. vtx .pos(ofs+1)=q.quad.p[1];
  349. vtx .pos(ofs+2)=q.quad.p[2];
  350. vtx .pos(ofs+3)=q.quad.p[3];
  351. quad.ind(i).set(ofs+0, ofs+1, ofs+2, ofs+3);
  352. ofs+=4;
  353. }
  354. setVtxDup();
  355. }
  356. weldVtx(VTX_TEX_ALL);
  357. // free
  358. Free(tex_set);
  359. Free(tex_y );
  360. return T;
  361. }
  362. /******************************************************************************/
  363. // EDGE TO POLY
  364. /******************************************************************************/
  365. MeshBase& MeshBase::edgeToPoly(MemPtr<Poly> polys)
  366. {
  367. polys.clear();
  368. if(vtxs() && edges() && edge.flag())
  369. {
  370. Byte *flag=Alloc<Byte>(edges()); CopyN(flag, edge.flag(), edges());
  371. // link vtx->edge
  372. Index vtx_edge; linkVtxEdge(vtx_edge);
  373. // get polys
  374. REPAD(e, edge)if(flag[e]&ETQ_LR) // for each solid edge
  375. REPD (side, 2)if(flag[e]&(side ? ETQ_R : ETQ_L)) // for each solid side
  376. {
  377. Poly &poly =polys.New().create(vtx.pos(), edge.id() ? edge.id(e) : -1); // start creating new poly and optionally set its ID from edge ID
  378. Int prev_vtx=edge .ind (e).c[!side], // setting 'prev' and 'cur' vertexes determines movement direction
  379. cur_vtx=edge .ind (e).c[ side], next_vtx;
  380. flag[e]&=( side ? ~ETQ_R : ~ETQ_L); // eat solid
  381. for(Int edge_cur=e; ; ) // start movement loop
  382. {
  383. next_vtx=-1; // set next vertex as unknown
  384. poly.addVtx(prev_vtx, edge_cur); // add 'prev' vertex to the poly list
  385. IndexGroup &ig=vtx_edge.group[cur_vtx]; // get next edge linked with 'cur_vtx'
  386. REPA(ig) // iterate all edges linked with 'cur_vtx' to find the next valid edge (which has solid info)
  387. {
  388. Int edge_test=ig[i]; if(edge_test==edge_cur) // find 'i' position in which the edge is equal to the current
  389. {
  390. Bool other_side=false; // work mode
  391. for(Int j=1; j<=ig.num; j++) // start from the next edge (+1) but finish also on the starting (edge_cur) because there are cases that only it's the correct one
  392. {
  393. edge_test=ig[(i+j)%ig.num]; Int *p=edge.ind(edge_test).c; Byte &fl=flag[edge_test], f=ETQ_R, nf=ETQ_L; // on the end when j==ig.num, (i+ig.num)%ig.num==i, this means that at the end will be checked the starting edge (edge_cur)
  394. next_vtx =p[1]; if(next_vtx==cur_vtx){next_vtx=p[0]; Swap(f, nf);} // make sure that the next vertex isn't set as the current one
  395. if(!other_side) // normal work mode
  396. {
  397. if(fl&f){fl&=~f; break;}else // encountered edge has desired info about solid, so let's eat it and finish
  398. {
  399. next_vtx=-1;
  400. if(fl&nf)other_side=true; // encountered edge has info about solid but from the other side, this means that now we'll have to skip all information about solid because we're not interested in them
  401. }
  402. }else // secondary work mode in which we skip information about encountered solid
  403. {
  404. if(fl&f && !(fl&nf))other_side=false; // we've encountered closing solid
  405. next_vtx=-1;
  406. }
  407. }
  408. edge_cur=edge_test;
  409. break;
  410. }
  411. }
  412. if(next_vtx<0)break;
  413. prev_vtx= cur_vtx;
  414. cur_vtx=next_vtx;
  415. }
  416. if(poly.vtx.elms()<=2)polys.removeLast();
  417. }
  418. // free
  419. Free(flag);
  420. }
  421. return T;
  422. }
  423. /******************************************************************************/
  424. // EDGE TO DEPTH
  425. /******************************************************************************/
  426. struct EdgeWall
  427. {
  428. VecI4 ind;
  429. Int id;
  430. };
  431. MeshBase& MeshBase::edgeToDepth(Bool tex_align)
  432. {
  433. Memb<EdgeWall> wall(256);
  434. Memb<Poly > polys ; edgeToPoly(polys);
  435. Int j=0, edges=0; FREPA(polys)edges+=polys[i].vtx.elms();
  436. MeshBase temp(2*(edges+polys.elms()), 0, 0, 0, VTX_TEX0);
  437. Vec2 *tex =temp.vtx .tex0();
  438. Flt *height= vtx .size();
  439. Vec *src = vtx .pos (),
  440. *dest =temp.vtx .pos ();
  441. Byte *flag = edge.flag();
  442. Int *eid = edge.id ();
  443. FREPA(polys)
  444. {
  445. Poly &poly=polys[i];
  446. Flt t=0, tex_scale=1;
  447. if(tex_align)
  448. {
  449. Flt length=poly.length3D();
  450. tex_scale =Max(1, RoundPos(length))/length;
  451. }
  452. {
  453. Int i =poly.vtx[poly.vtx.last()].index,
  454. e =poly.vtx[poly.vtx.last()].edge ;
  455. Flt h =(height ? height[i] : 1);
  456. Vec prev =src [i];
  457. dest[j ]=dest[j+1]=prev; dest[j].z+=h;
  458. tex [j ].set(0, 0);
  459. tex [j+1].set(0, h);
  460. MFREPD(vtx, poly.vtx)
  461. {
  462. if(!flag || !(flag[e]&ETQ_NO_PHYS))
  463. {
  464. EdgeWall &w=wall.New();
  465. w.ind.set(j, j+2, j+3, j+1);
  466. if(eid)w.id =eid[e];
  467. }
  468. j+=2;
  469. i=poly.vtx[vtx].index;
  470. e=poly.vtx[vtx].edge ;
  471. h=(height ? height[i] : 1);
  472. Vec &next=src [i]; t+=Dist(prev, next)*tex_scale;
  473. dest[j ]=dest[j+1]=next; dest[j].z+=h;
  474. tex [j ].set(t, 0);
  475. tex [j+1].set(t, h);
  476. prev=next;
  477. }
  478. j+=2;
  479. }
  480. }
  481. temp.quad._elms=wall.elms();
  482. temp.include(QUAD_IND|(eid ? QUAD_ID : 0));
  483. REPA(wall)
  484. {
  485. EdgeWall &w=wall[i];
  486. temp.quad.ind(i)=w.ind;
  487. if(temp.quad.id())temp.quad.id (i)=w.id ;
  488. }
  489. Swap(T, temp); return T;
  490. }
  491. /******************************************************************************/
  492. // EDGE TO TRI
  493. /******************************************************************************/
  494. #define ETT_EPS 0.09f
  495. struct ETT_TRI
  496. {
  497. VecI ind;
  498. Int id;
  499. };
  500. struct FloatPtr // Float + Pointer
  501. {
  502. Flt f; // float
  503. Ptr p; // pointer
  504. static Int Compare(C FloatPtr &a, C FloatPtr &b) {return ::Compare(a.f, b.f);}
  505. };
  506. struct ETT
  507. {
  508. Meml<Poly> polys;
  509. Vec *pos; Int vtxs;
  510. FloatPtr *fi ; Int fis;
  511. Rects rects;
  512. Index rect_vtx;
  513. IndexPtr vtx_poly;
  514. Memb<ETT_TRI> mtri ;
  515. MemlNode *mpoly;
  516. Poly * poly;
  517. ~ETT()
  518. {
  519. /*#if DEBUG
  520. extern Int I;
  521. if(polys.elms())
  522. {
  523. do{
  524. GetInput(); CAMHndl(0.00001f, 100, CAMH_ZOOM|(Ms.b(1)?CAMH_MOVE:CAMH_ROT));
  525. DISPClr(GREY);
  526. DRAWSet(Vec2(1)/CAM_CUR.dist, -CAM_CUR.at.xy);
  527. REPA(mtri)
  528. {
  529. TRIDraw(Tri2(pos[mtri[i].c[0]].xy,
  530. pos[mtri[i].c[1]].xy,
  531. pos[mtri[i].c[2]].xy), BLACK);
  532. }
  533. Int j=0; MFREP(polys)POLYDraw(memn->dColI(j++));
  534. DRAWSet(Vec2(1), Vec2(0));
  535. D.text(0, 0.7f, S+polys.elms()+" Poly(s) left on "+I);
  536. DISPFlip();
  537. }while(!Kb.bp(KB_SPACE));
  538. // Exit(S+polys.elms()+" Poly(s) left on "+I);
  539. }
  540. #endif*/
  541. Free(fi);
  542. }
  543. void vtxRem(MemlNode *vtx)
  544. {
  545. Int index=poly->vtx[vtx].index;
  546. IndexPtrGroup &ig =vtx_poly.group[index]; ig.subVal(mpoly); if(!ig.num)rect_vtx.group[rects.index(pos[index].xy)].subVal(index);
  547. poly->removeVtx(vtx);
  548. }
  549. Int testTri(MemlNode *vtx, Bool test) // returns 0-not ok try next vertex, 1-added triangle and repeat the test, 2-ok finish the test
  550. {
  551. Int p0=poly->vtx[poly->vtx.loopPrev(vtx)].index,
  552. p1=poly->vtx[ vtx ].index,
  553. p2=poly->vtx[poly->vtx.loopNext(vtx)].index;
  554. Vec &P0=pos[p0],
  555. &P1=pos[p1],
  556. &P2=pos[p2];
  557. Tri2 tri(P0.xy, P1.xy, P2.xy);
  558. if(test ? tri.valid() : true)
  559. {
  560. // test if triangle does not contain any points inside
  561. Plane plane(P0, GetNormal(P0, P1, P2));
  562. Int vtx_cut=-1;
  563. Flt dist;
  564. Rect rect =tri; rect.extend(EPS);
  565. VecI2 rect_min=rects.coords(rect.min),
  566. rect_max=rects.coords(rect.max);
  567. for(Int y=rect_min.y; y<=rect_max.y; y++)
  568. for(Int x=rect_min.x; x<=rect_max.x; x++)
  569. {
  570. IndexGroup &ig=rect_vtx.group[rects.index(VecI2(x, y))];
  571. REPAD(v, ig)
  572. {
  573. Int pt=ig[v];
  574. if( pt!=p0 && pt!=p1 && pt!=p2)
  575. {
  576. Vec2 &vt=pos[pt].xy;
  577. if(test ? CutsEps(vt, tri) : Cuts(vt, tri))
  578. if(Abs(Dist(pos[pt], plane))<=ETT_EPS)
  579. {
  580. Flt d=Min(DistPointEdge(vt, tri.p[0], tri.p[1]), DistPointEdge(vt, tri.p[1], tri.p[2]));
  581. if(vtx_cut<0 || d<dist){vtx_cut=pt; dist=d;}
  582. }
  583. }
  584. }
  585. }
  586. if(vtx_cut<0) // no vtx inside
  587. {
  588. // create the tri basing on the source 3
  589. ETT_TRI &et=mtri.New();
  590. et.ind.set(p0, p1, p2);
  591. et.id =poly->id;
  592. vtxRem(vtx);
  593. if(poly->vtx.elms()<=2) // there won't be anything more out of the poly
  594. {
  595. for(; poly->vtx.elms(); )vtxRem(poly->vtx.first());
  596. MemlNode *next=mpoly->next();
  597. poly->del(); polys.remove(mpoly);
  598. mpoly=next;
  599. return 2;
  600. }
  601. return 1;
  602. }
  603. // vtx inside
  604. MemlNode *mpoly_cut=null;
  605. IndexPtrGroup &ig =vtx_poly.group[vtx_cut];
  606. REPAD(p, ig)
  607. {
  608. MemlNode *tpoly=(MemlNode*)ig[p]; if(tpoly==mpoly){mpoly_cut=null; break;} // cuts self & skip
  609. if(((Poly*)tpoly->data())->infinite())mpoly_cut=tpoly;
  610. }
  611. if(mpoly_cut) // link two polys
  612. {
  613. Poly &poly2=*(Poly*)mpoly_cut->data();
  614. MemlNode *vtx2=null; MFREP(poly2.vtx)
  615. {
  616. Int index=poly2.vtx[i].index; if(index==vtx_cut)vtx2=i;
  617. vtx_poly.group[index].changeVal(mpoly_cut, mpoly);
  618. }
  619. poly->link(poly2, vtx, vtx2); poly2.del(); polys.remove(mpoly_cut);
  620. if(poly->vtx.elms()>fis)Realloc(fi, fis=poly->vtx.elms(), 0);
  621. return 1;
  622. }
  623. }
  624. return 0;
  625. }
  626. };
  627. MeshBase& MeshBase::edgeToTri(Bool set_id) // assumes: weldVtx, removeUnusedVtxs, this method is required not to modify vertexes (only faces should be changed)
  628. {
  629. if(vtxs() && edges() && edge.flag())
  630. {
  631. ETT ett;
  632. // convert to polys
  633. ett.vtxs=vtxs();
  634. ett.pos =vtx.pos();
  635. edgeToPoly(ett.polys);
  636. // link rect->vtxs
  637. ett.rects .set (Rect(T), ett.vtxs);
  638. ett.rect_vtx.create(ett.rects.num(), ett.vtxs);
  639. FREP(ett.vtxs)ett.rect_vtx.elmGroup(ett.rects.index(ett.pos[i].xy), i); ett.rect_vtx.set();
  640. // link vtx->polys
  641. ett.vtx_poly.create(ett.vtxs);
  642. MFREP(ett.polys)MFREPD(vtx, ett.polys[i].vtx)ett.vtx_poly.incGroup(ett.polys[i].vtx[vtx].index ); ett.vtx_poly.set();
  643. MFREP(ett.polys)MFREPD(vtx, ett.polys[i].vtx)ett.vtx_poly.addElm (ett.polys[i].vtx[vtx].index, i);
  644. // create angle array
  645. ett.fis=0; MFREP(ett.polys)
  646. {
  647. Poly &poly=ett.polys[i]; poly.setAngle();
  648. ett.fis=Max(ett.fis, poly.vtx.elms());
  649. }
  650. Alloc(ett.fi, ett.fis);
  651. // convert polys to triangles
  652. REPD(test, 2)for(ett.mpoly=ett.polys.first(); ett.mpoly; )
  653. {
  654. ett.poly=&ett.polys[ett.mpoly];
  655. if(!ett.poly->infinite())
  656. {
  657. test:;
  658. FloatPtr *fi=ett.fi;
  659. MFREPD(vtx, ett.poly->vtx)
  660. {
  661. fi->p=vtx;
  662. fi->f=ett.poly->vtx[vtx].angle;
  663. fi++;
  664. }
  665. Sort (ett.fi, ett.poly->vtx.elms(), FloatPtr::Compare);
  666. FREPA(ett.poly->vtx)
  667. {
  668. Flt a =ett.fi[i].f;
  669. if( a>=PI-EPS)break;
  670. if( a> EPS)
  671. {
  672. Int c=ett.testTri((MemlNode*)ett.fi[i].p, test!=0);
  673. if( c==1)goto test;
  674. if( c==2)goto done;
  675. }
  676. }
  677. }
  678. ett.mpoly=ett.mpoly->next();
  679. done:;
  680. }
  681. // free & create
  682. exclude(ADJ_ALL|FACE_ALL); tri._elms=ett.mtri.elms();
  683. include(TRI_IND|(set_id ? TRI_ID : 0));
  684. FREPA(ett.mtri)
  685. {
  686. ETT_TRI &et=ett.mtri[i];
  687. tri.ind(i)=et.ind;
  688. if(tri.id())tri.id (i)=et.id ;
  689. }
  690. }
  691. return T;
  692. }
  693. /******************************************************************************/
  694. // TRI TO QUAD
  695. /******************************************************************************/
  696. struct TriLink
  697. {
  698. Int tri[2];
  699. Flt length2;
  700. void set(Int t0, Int t1, Flt length2) {tri[0]=t0; tri[1]=t1; T.length2=length2;}
  701. static Int Compare(C TriLink &l0, C TriLink &l1)
  702. {
  703. if(l0.length2>l1.length2)return -1;
  704. if(l0.length2<l1.length2)return +1;
  705. return 0;
  706. }
  707. };
  708. MeshBase& MeshBase::triToQuad(Flt cos)
  709. {
  710. if(tris())
  711. {
  712. setAdjacencies(true, false);
  713. setFaceNormals();
  714. Memb<TriLink> link(64);
  715. FREPA(tri)REPD(j, 3)
  716. {
  717. Int af =tri.adjFace(i).c[j];
  718. if( af!=-1 && !(af&SIGN_BIT) && i<af && Dot(tri.nrm(i), tri.nrm(af))>=cos) // compare to -1 and not >=0 because it can have SIGN_BIT
  719. {
  720. Int *p0=tri.ind(i ).c,
  721. *p1=tri.ind(af).c;
  722. Int i0=j;
  723. REPD(i1, 3)if(p0[i0]==p1[(i1+1)%3] && p0[(i0+1)%3]==p1[i1])
  724. {
  725. Vec &a=vtx.pos(p0[ i0 ]),
  726. &b=vtx.pos(p1[(i1+2)%3]),
  727. &c=vtx.pos(p0[(i0+1)%3]),
  728. &d=vtx.pos(p0[(i0+2)%3]),
  729. nrm=Cross(tri.nrm(i), b-d);
  730. if(DistPointPlane(c, d, nrm)> EPS
  731. && DistPointPlane(a, d, nrm)<-EPS)link.New().set(i, af, Dist2(a, c));
  732. break;
  733. }
  734. }
  735. }
  736. if(link.elms())
  737. {
  738. exclude(ADJ_ALL);
  739. link.sort(TriLink::Compare);
  740. Memt<Int> linked; linked.setNum(tris()); SetMemN(linked.data(), 0xFF, linked.elms());
  741. FREPA(link)
  742. {
  743. TriLink &l=link[i];
  744. if(linked[l.tri[0]]<0 && linked[l.tri[1]]<0)
  745. {
  746. linked[l.tri[0]]=l.tri[1];
  747. linked[l.tri[1]]=l.tri[0];
  748. }
  749. }
  750. Memt<Bool> is; is.setNum(T.tris()); FREPA(tri)is[i]=(linked[i]<0);
  751. Int tris=CountIs(is);
  752. MeshBase temp(0, 0, tris, quads()+(T.tris()-tris)/2);
  753. CopyIs(temp.tri .ind(), tri .ind(), is );
  754. CopyN (temp.quad.ind(), quad.ind(), T.quads());
  755. VecI4 *_quad=temp.quad.ind()+quads();
  756. FREPA(tri)
  757. {
  758. Int n2=linked[i];
  759. if(i<n2)
  760. {
  761. Int *p0=tri.ind(i ).c,
  762. *p1=tri.ind(n2).c;
  763. Int i0, i1; for(i0=3; --i0>=0; )for(i1=3; --i1>=0; )if(p0[i0]==p1[(i1+1)%3] && p0[(i0+1)%3]==p1[i1])goto found; found:;
  764. (_quad++)->set(p1[(i1+2)%3], p0[(i0+1)%3], p0[(i0+2)%3], p0[i0]);
  765. }
  766. }
  767. Swap(tri , temp.tri );
  768. Swap(quad, temp.quad);
  769. }
  770. }
  771. return T;
  772. }
  773. /******************************************************************************/
  774. // QUAD TO TRI
  775. /******************************************************************************/
  776. MeshBase& MeshBase::quadToTri(Flt cos)
  777. {
  778. if(quads() && cos>-1) // if cos<=-1 then keep all quads
  779. if(!tris() || (!tri.ind())==(!quad.ind())) // if existence of vtx ID's match
  780. {
  781. if(tris() && !tri.nrm() && quad.nrm())setFaceNormals(); // if there are tris, and quads have normals but tris don't, then set normals for tris
  782. exclude(ADJ_ALL);
  783. UInt f=flag();
  784. if(f&QUAD_NRM )f|=TRI_NRM ;
  785. if(f&QUAD_FLAG)f|=TRI_FLAG;
  786. if(f&QUAD_ID )f|=TRI_ID ;
  787. C Vec *pos=vtx.pos();
  788. if(cos>1 || !quad.ind() || !pos) // convert all quads to tris
  789. {
  790. MeshBase temp(0, 0, tris()+quads()*2, 0, f);
  791. CopyN(temp.tri.ind (), tri.ind (), tris());
  792. CopyN(temp.tri.nrm (), tri.nrm (), tris());
  793. CopyN(temp.tri.flag(), tri.flag(), tris());
  794. CopyN(temp.tri.id (), tri.id (), tris());
  795. if(quad.ind())
  796. {
  797. VecI4 *s= quad.ind();
  798. VecI *d=temp.tri.ind()+tris();
  799. REPA(quad)
  800. {
  801. d[0].set(s->c[0], s->c[1], s->c[3]);
  802. d[1].set(s->c[3], s->c[1], s->c[2]); s++; d+=2;
  803. }
  804. }
  805. if(quad.nrm())
  806. {
  807. Vec *s= quad.nrm(),
  808. *d=temp.tri.nrm()+tris();
  809. REPA(quad){d[0]=d[1]=*s++; d+=2;}
  810. }
  811. if(quad.flag())
  812. {
  813. Byte *s= quad.flag(),
  814. *d=temp.tri.flag()+tris();
  815. REPA(quad){d[0]=d[1]=*s++; d+=2;}
  816. }
  817. if(quad.id())
  818. {
  819. Int *s= quad.id(),
  820. *d=temp.tri.id()+tris();
  821. REPA(quad){d[0]=d[1]=*s++; d+=2;}
  822. }
  823. Swap(tri , temp.tri );
  824. Swap(quad, temp.quad);
  825. }else
  826. {
  827. // check which quads should be left/separated
  828. Memt<Bool> keep; keep.setNum(quads());
  829. Int keep_num=0, split_num=0;
  830. REPA(quad)
  831. {
  832. C VecI4 &p =quad.ind(i);
  833. C Vec &p0=pos[p.x],
  834. &p1=pos[p.y],
  835. &p2=pos[p.z],
  836. &p3=pos[p.w];
  837. if(keep[i]=(Dot(GetNormal(p0, p1, p3), GetNormal(p1, p2, p3))>=cos))keep_num++;else split_num++;
  838. }
  839. // separate
  840. MeshBase temp(0, 0, tris()+split_num*2, keep_num, f);
  841. CopyN(temp.tri.ind (), tri.ind (), tris());
  842. CopyN(temp.tri.nrm (), tri.nrm (), tris());
  843. CopyN(temp.tri.flag(), tri.flag(), tris());
  844. CopyN(temp.tri.id (), tri.id (), tris());
  845. if(quad.ind())
  846. {
  847. VecI4 *s = quad.ind(),
  848. *dq=temp.quad.ind();
  849. VecI *dt=temp.tri .ind()+tris();
  850. FREPA(quad)
  851. {
  852. if(keep[i])
  853. {
  854. *dq++=*s++;
  855. }else
  856. {
  857. dt[0].set(s->c[0], s->c[1], s->c[3]);
  858. dt[1].set(s->c[3], s->c[1], s->c[2]); dt+=2; s++;
  859. }
  860. }
  861. }
  862. if(quad.nrm())
  863. {
  864. Vec *s = quad.nrm(),
  865. *dq=temp.quad.nrm(),
  866. *dt=temp.tri .nrm()+tris();
  867. FREPA(quad)
  868. {
  869. if(keep[i])
  870. {
  871. *dq++=*s++;
  872. }else
  873. {
  874. dt[0]=dt[1]=*s++; dt+=2;}
  875. }
  876. }
  877. if(quad.flag())
  878. {
  879. Byte *s = quad.flag(),
  880. *dq=temp.quad.flag(),
  881. *dt=temp.tri .flag()+tris();
  882. FREPA(quad)
  883. {
  884. if(keep[i])
  885. {
  886. *dq++=*s++;
  887. }else
  888. {
  889. dt[0]=dt[1]=*s++; dt+=2;
  890. }
  891. }
  892. }
  893. if(quad.id())
  894. {
  895. Int *s = quad.id(),
  896. *dq=temp.quad.id(),
  897. *dt=temp.tri .id()+tris();
  898. FREPA(quad)
  899. {
  900. if(keep[i])
  901. {
  902. *dq++=*s++;
  903. }else
  904. {
  905. dt[0]=dt[1]=*s++; dt+=2;
  906. }
  907. }
  908. }
  909. Swap(tri , temp.tri );
  910. Swap(quad, temp.quad);
  911. }
  912. }
  913. return T;
  914. }
  915. MeshBase& MeshBase::quadToTri(C MemPtr<Int> &quads)
  916. {
  917. Memt<Int> actual_quads; FREPA(quads){Int q=quads[i]; if(InRange(q, T.quad))actual_quads.binaryInclude(q, Compare);}
  918. if( actual_quads.elms())
  919. {
  920. if(tris() && !tri.nrm() && quad.nrm())setFaceNormals(); // if there are tris, and quads have normals but tris don't, then set normals for tris
  921. exclude(ADJ_ALL);
  922. UInt f=flag();
  923. if(f&QUAD_NRM )f|=TRI_NRM ;
  924. if(f&QUAD_FLAG)f|=TRI_FLAG;
  925. if(f&QUAD_ID )f|=TRI_ID ;
  926. MeshBase temp(0, 0, tris()+actual_quads.elms()*2, 0, f);
  927. CopyN(temp.tri.ind (), tri.ind (), tris());
  928. CopyN(temp.tri.nrm (), tri.nrm (), tris());
  929. CopyN(temp.tri.flag(), tri.flag(), tris());
  930. CopyN(temp.tri.id (), tri.id (), tris());
  931. if(quad.ind())
  932. {
  933. VecI *d=temp.tri.ind()+tris();
  934. FREPA(actual_quads)
  935. {
  936. VecI4 s=quad.ind(actual_quads[i]);
  937. d[0].set(s.c[0], s.c[1], s.c[3]);
  938. d[1].set(s.c[3], s.c[1], s.c[2]); d+=2;
  939. }
  940. }
  941. if(quad.nrm())
  942. {
  943. Vec *d=temp.tri.nrm()+tris();
  944. FREPA(actual_quads){d[0]=d[1]=quad.nrm(actual_quads[i]); d+=2;}
  945. }
  946. if(quad.flag())
  947. {
  948. Byte *d=temp.tri.flag()+tris();
  949. FREPA(actual_quads){d[0]=d[1]=quad.flag(actual_quads[i]); d+=2;}
  950. }
  951. if(quad.id())
  952. {
  953. Int *d=temp.tri.id()+tris();
  954. FREPA(actual_quads){d[0]=d[1]=quad.id(actual_quads[i]); d+=2;}
  955. }
  956. Swap(tri, temp.tri);
  957. removeQuads(actual_quads, false); // no need to remove vtxs because all of them are used by tris
  958. }
  959. return T;
  960. }
  961. /******************************************************************************/
  962. }
  963. /******************************************************************************/