Mshb Fix.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. namespace EE{
  4. /******************************************************************************
  5. MeshBase& fixSolid (Bool swapped ); // fix edge winding according to ETQ_FLAG
  6. MeshBase& MeshBase::fixSolid(Bool swapped)
  7. {
  8. if(edge.ind() && edge.flag())
  9. {
  10. exclude(ADJ_ALL);
  11. Memt<Bool> is; is.setNum(edges());
  12. FREPA(edge)
  13. {
  14. Byte &flag=edge.flag(i);
  15. if(flag&ETQ_NO_PHYS || (flag&ETQ_LR)==ETQ_LR || !(flag&ETQ_LR))is[i]=false;else
  16. {
  17. is[i]=true;
  18. if(swapped){if(flag&ETQ_L) edge.ind(i).reverse();else flag=(flag&(~ETQ_LR))|ETQ_L; }
  19. else {if(flag&ETQ_R){edge.ind(i).reverse(); flag=(flag&(~ETQ_LR))|ETQ_L;}}
  20. }
  21. }
  22. keepEdges(is);
  23. }
  24. return T;
  25. }
  26. /******************************************************************************
  27. enum WINDING_TYPE
  28. {
  29. WINDING_DUNNO,
  30. WINDING_OK ,
  31. WINDING_WRONG,
  32. };
  33. struct FixWindingClass
  34. {
  35. Byte * tri_flag;
  36. Byte *quad_flag;
  37. VecI * tri_ind ;
  38. VecI4 *quad_ind ;
  39. Index * vtx_face;
  40. };
  41. static void FixWinding(FixWindingClass &fw, Int face, Bool ok)
  42. {
  43. Int *p, *tp, vrts, tvrts, tface;
  44. if(face&SIGN_BIT)
  45. {
  46. fw.quad_flag[face^SIGN_BIT]=(ok ? WINDING_OK : WINDING_WRONG);
  47. p=fw.quad_ind [face^SIGN_BIT].c;
  48. vrts=4;
  49. }else
  50. {
  51. fw.tri_flag[face]=(ok ? WINDING_OK : WINDING_WRONG);
  52. p=fw.tri_ind [face].c;
  53. vrts=3;
  54. }
  55. REP(vrts)
  56. {
  57. Int v =p[ i ],
  58. next=p[(i+1)%vrts];
  59. IndexGroup &ig=fw.vtx_face->group[v];
  60. REPAD(f, ig)
  61. {
  62. tface=ig[f];
  63. if(tface&SIGN_BIT){if(fw.quad_flag[tface^SIGN_BIT])continue; tp=fw.quad_ind[tface^SIGN_BIT].c; tvrts=4;}else
  64. {if(fw. tri_flag[tface ])continue; tp=fw. tri_ind[tface ].c; tvrts=3;}
  65. REPD(tn, tvrts)if(tp[tn]==v)
  66. {
  67. if(tp[(tn+tvrts-1)%tvrts]==next)FixWinding(fw, tface, ok);else // tprev==next
  68. if(tp[(tn +1)%tvrts]==next)FixWinding(fw, tface, !ok); // tnext==next
  69. break;
  70. }
  71. }
  72. }
  73. }
  74. MeshBase& fixWinding (Int face, Bool ok=true); // recursive fix of adjacent faces winding, according to given 'face' index and if it's winded correctly
  75. MeshBase& MeshBase::fixWinding(Int face, Bool ok)
  76. {
  77. if((face&SIGN_BIT) ? InRange(face^SIGN_BIT, quad) : InRange(face, tri))
  78. {
  79. Byte * tri_flag=AllocZero<Byte>(tris ()),
  80. *quad_flag=AllocZero<Byte>(quads());
  81. // link vtx->face
  82. Index vtx_face; linkVtxFace(vtx_face);
  83. // fix winding
  84. FixWindingClass fw;
  85. fw. tri_flag= tri_flag;
  86. fw.quad_flag=quad_flag;
  87. fw. tri_ind= tri.ind();
  88. fw.quad_ind= quad.ind();
  89. fw.vtx_face= &vtx_face;
  90. FixWinding(fw, face, ok);
  91. FREPA(tri )if( tri_flag[i]==WINDING_WRONG)tri .ind(i).reverse();
  92. FREPA(quad)if(quad_flag[i]==WINDING_WRONG)quad.ind(i).reverse();
  93. // free
  94. Free( tri_flag);
  95. Free(quad_flag);
  96. }
  97. return T;
  98. }
  99. /******************************************************************************/
  100. struct VTX
  101. {
  102. Int dup;
  103. Flt tex_min, tex_max;
  104. void init(Flt tex)
  105. {
  106. dup=0;
  107. tex_min=tex_max=tex;
  108. }
  109. };
  110. MeshBase& MeshBase::fixTexWrapping(Byte tex_index)
  111. {
  112. if(InRange(tex_index, 3))
  113. if(Vec2 *tex=((tex_index==0) ? vtx.tex0() : (tex_index==1) ? vtx.tex1() : vtx.tex2()))
  114. {
  115. Int *p, p0, p1, p2, p3, j;
  116. Memt<VTX> vs; vs.setNum(vtxs());
  117. // get tex range
  118. Flt x;
  119. FREPA(vtx)vs[i].init(tex[i].x);
  120. FREPA(tri)
  121. {
  122. p=tri.ind(i).c; p0=p[0]; p1=p[1]; p2=p[2];
  123. x=tex[p0].x; if(x<vs[p1].tex_min)vs[p1].tex_min=x;else if(x>vs[p1].tex_max)vs[p1].tex_max=x;
  124. if(x<vs[p2].tex_min)vs[p2].tex_min=x;else if(x>vs[p2].tex_max)vs[p2].tex_max=x;
  125. x=tex[p1].x; if(x<vs[p0].tex_min)vs[p0].tex_min=x;else if(x>vs[p0].tex_max)vs[p0].tex_max=x;
  126. if(x<vs[p2].tex_min)vs[p2].tex_min=x;else if(x>vs[p2].tex_max)vs[p2].tex_max=x;
  127. x=tex[p2].x; if(x<vs[p0].tex_min)vs[p0].tex_min=x;else if(x>vs[p0].tex_max)vs[p0].tex_max=x;
  128. if(x<vs[p1].tex_min)vs[p1].tex_min=x;else if(x>vs[p1].tex_max)vs[p1].tex_max=x;
  129. }
  130. FREPA(quad)
  131. {
  132. p=quad.ind(i).c; p0=p[0]; p1=p[1]; p2=p[2]; p3=p[3];
  133. x=tex[p0].x; if(x<vs[p1].tex_min)vs[p1].tex_min=x;else if(x>vs[p1].tex_max)vs[p1].tex_max=x;
  134. if(x<vs[p2].tex_min)vs[p2].tex_min=x;else if(x>vs[p2].tex_max)vs[p2].tex_max=x;
  135. if(x<vs[p3].tex_min)vs[p3].tex_min=x;else if(x>vs[p3].tex_max)vs[p3].tex_max=x;
  136. x=tex[p1].x; if(x<vs[p0].tex_min)vs[p0].tex_min=x;else if(x>vs[p0].tex_max)vs[p0].tex_max=x;
  137. if(x<vs[p2].tex_min)vs[p2].tex_min=x;else if(x>vs[p2].tex_max)vs[p2].tex_max=x;
  138. if(x<vs[p3].tex_min)vs[p3].tex_min=x;else if(x>vs[p3].tex_max)vs[p3].tex_max=x;
  139. x=tex[p2].x; if(x<vs[p0].tex_min)vs[p0].tex_min=x;else if(x>vs[p0].tex_max)vs[p0].tex_max=x;
  140. if(x<vs[p1].tex_min)vs[p1].tex_min=x;else if(x>vs[p1].tex_max)vs[p1].tex_max=x;
  141. if(x<vs[p3].tex_min)vs[p3].tex_min=x;else if(x>vs[p3].tex_max)vs[p3].tex_max=x;
  142. x=tex[p3].x; if(x<vs[p0].tex_min)vs[p0].tex_min=x;else if(x>vs[p0].tex_max)vs[p0].tex_max=x;
  143. if(x<vs[p1].tex_min)vs[p1].tex_min=x;else if(x>vs[p1].tex_max)vs[p1].tex_max=x;
  144. if(x<vs[p2].tex_min)vs[p2].tex_min=x;else if(x>vs[p2].tex_max)vs[p2].tex_max=x;
  145. }
  146. // get odd vtxs (tex.range >= 2/3)
  147. Int dups=0;
  148. FREPA(vtx)if(vs[i].tex_max-vs[i].tex_min>=2.0f/3)vs[i].dup=vtxs()+(dups++);
  149. // copy mshb
  150. {
  151. MeshBase temp(vtxs()+dups, 0, 0, 0, flag()); temp.copyVtxs(T);
  152. tex=((tex_index==0) ? temp.vtx.tex0() : (tex_index==1) ? temp.vtx.tex1() : temp.vtx.tex2());
  153. FREPA(vtx)if(vs[i].dup)
  154. {
  155. j=vs[i].dup; copyVtx(i, temp, j);
  156. Int d=Trunc(vs[i].tex_max-vs[i].tex_min+2.0f/3);
  157. if(Abs(tex[j].x-vs[i].tex_max)<Abs(tex[i].x-vs[i].tex_min))tex[i].x-=d;else tex[j].x+=d;
  158. }
  159. Swap(vtx, temp.vtx);
  160. }
  161. // correct indexing to nearest tex.coord
  162. FREPA(tri)
  163. {
  164. p=tri.ind(i).c; p0=p[0]; p1=p[1]; p2=p[2];
  165. if(j=vs[p0].dup)
  166. {
  167. if(!vs[p1].dup){if(Abs(tex[p1].x-tex[j].x)<Abs(tex[p1].x-tex[p0].x))p[0]=j;}else
  168. if(!vs[p2].dup){if(Abs(tex[p2].x-tex[j].x)<Abs(tex[p2].x-tex[p0].x))p[0]=j;}
  169. }
  170. if(j=vs[p1].dup)
  171. {
  172. if(!vs[p0].dup){if(Abs(tex[p0].x-tex[j].x)<Abs(tex[p0].x-tex[p1].x))p[1]=j;}else
  173. if(!vs[p2].dup){if(Abs(tex[p2].x-tex[j].x)<Abs(tex[p2].x-tex[p1].x))p[1]=j;}
  174. }
  175. if(j=vs[p2].dup)
  176. {
  177. if(!vs[p0].dup){if(Abs(tex[p0].x-tex[j].x)<Abs(tex[p0].x-tex[p2].x))p[2]=j;}else
  178. if(!vs[p1].dup){if(Abs(tex[p1].x-tex[j].x)<Abs(tex[p1].x-tex[p2].x))p[2]=j;}
  179. }
  180. }
  181. FREPA(quad)
  182. {
  183. p=quad.ind(i).c; p0=p[0]; p1=p[1]; p2=p[2]; p3=p[3];
  184. if(j=vs[p0].dup)
  185. {
  186. if(!vs[p1].dup){if(Abs(tex[p1].x-tex[j].x)<Abs(tex[p1].x-tex[p0].x))p[0]=j;}else
  187. if(!vs[p2].dup){if(Abs(tex[p2].x-tex[j].x)<Abs(tex[p2].x-tex[p0].x))p[0]=j;}else
  188. if(!vs[p3].dup){if(Abs(tex[p3].x-tex[j].x)<Abs(tex[p3].x-tex[p0].x))p[0]=j;}
  189. }
  190. if(j=vs[p1].dup)
  191. {
  192. if(!vs[p0].dup){if(Abs(tex[p0].x-tex[j].x)<Abs(tex[p0].x-tex[p1].x))p[1]=j;}else
  193. if(!vs[p2].dup){if(Abs(tex[p2].x-tex[j].x)<Abs(tex[p2].x-tex[p1].x))p[1]=j;}else
  194. if(!vs[p3].dup){if(Abs(tex[p3].x-tex[j].x)<Abs(tex[p3].x-tex[p1].x))p[1]=j;}
  195. }
  196. if(j=vs[p2].dup)
  197. {
  198. if(!vs[p0].dup){if(Abs(tex[p0].x-tex[j].x)<Abs(tex[p0].x-tex[p2].x))p[2]=j;}else
  199. if(!vs[p1].dup){if(Abs(tex[p1].x-tex[j].x)<Abs(tex[p1].x-tex[p2].x))p[2]=j;}else
  200. if(!vs[p3].dup){if(Abs(tex[p3].x-tex[j].x)<Abs(tex[p3].x-tex[p2].x))p[2]=j;}
  201. }
  202. if(j=vs[p3].dup)
  203. {
  204. if(!vs[p0].dup){if(Abs(tex[p0].x-tex[j].x)<Abs(tex[p0].x-tex[p3].x))p[3]=j;}else
  205. if(!vs[p1].dup){if(Abs(tex[p1].x-tex[j].x)<Abs(tex[p1].x-tex[p3].x))p[3]=j;}else
  206. if(!vs[p2].dup){if(Abs(tex[p2].x-tex[j].x)<Abs(tex[p2].x-tex[p3].x))p[3]=j;}
  207. }
  208. }
  209. }
  210. return T;
  211. }
  212. /******************************************************************************/
  213. MeshBase& MeshBase::fixTexOffset(Byte tex_index)
  214. {
  215. if(InRange(tex_index, 3))
  216. if(Vec2 *tex=((tex_index==0) ? vtx.tex0() : (tex_index==1) ? vtx.tex1() : vtx.tex2()))
  217. {
  218. exclude(VTX_DUP);
  219. Index vtx_vtx; linkVtxVtxOnFace(vtx_vtx); // link vertexes together
  220. Memt<Int , 16384> mvtx;
  221. Memt<Int , 16384> madd;
  222. Memt<Bool, 32768> vtx_is; vtx_is.setNumZero(vtxs());
  223. REPA(vtx)if(!vtx_is[i]) // process all vertexes
  224. {
  225. // get list of all vertexes that are connected together
  226. mvtx.clear();
  227. madd.add(i); vtx_is[i]=true;
  228. for(; madd.elms(); )
  229. {
  230. Int vtx=madd.pop();
  231. mvtx.add(vtx);
  232. IndexGroup &ig=vtx_vtx.group[vtx];
  233. REPA(ig)
  234. {
  235. Int v=ig[i]; if(!vtx_is[v])
  236. {
  237. madd.add(v);
  238. vtx_is[v]=true;
  239. }
  240. }
  241. }
  242. // calculate their average texture coordinates
  243. if(mvtx.elms())
  244. {
  245. Vec2 min, max; min=max=tex[mvtx.last()];
  246. REP(mvtx.elms()-1)
  247. {
  248. C Vec2 &t=tex[mvtx[i]];
  249. if(t.x<min.x)min.x=t.x;else if(t.x>max.x)max.x=t.x;
  250. if(t.y<min.y)min.y=t.y;else if(t.y>max.y)max.y=t.y;
  251. }
  252. VecI2 center=Floor(Avg(min, max)); // always try to fit UV's in 0..1, even if the Average is -0.1 which translates to -1..0 range, because material atlas generation tests for 0..1 range
  253. if(center.any())
  254. {
  255. Vec2 offset=-center; REPA(mvtx)tex[mvtx[i]]+=offset; // apply offset
  256. }
  257. }
  258. }
  259. }
  260. return T;
  261. }
  262. /******************************************************************************/
  263. }
  264. /******************************************************************************/