MegaRelax.cs 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. 
  2. using UnityEngine;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. #if false
  6. public class DWordTab
  7. {
  8. public List<int> values = new List<int>();
  9. }
  10. public class RelaxModData
  11. {
  12. public List<DWordTab> nbor = new List<DWordTab>(); // Array of neighbors for each vert.
  13. BitArray vis; // visibility of edges on path to neighbors.
  14. int[] fnum = null; //new List<int>(); //0; // Number of faces for each vert.
  15. BitArray sel; // Selection information.
  16. int vnum = 0; // Size of above arrays
  17. void MaybeAppendNeighbor(int vert, int index, ref int max)
  18. {
  19. for ( int k1 = 0; k1 < max; k1++ )
  20. {
  21. if ( nbor[vert].values[k1] == index )
  22. return;
  23. }
  24. //DWORD dwi = (DWORD)index;
  25. nbor[vert].values.Add(index); //Append(1, &dwi, 1);
  26. max++;
  27. }
  28. //RelaxModData()
  29. //{
  30. //nbor = NULL;
  31. //vis = NULL;
  32. //fnum = NULL;
  33. //vnum = 0;
  34. //}
  35. void Clear()
  36. {
  37. nbor.Clear();
  38. //vis.Clear();
  39. fnum = null;
  40. }
  41. void SetVNum(int num)
  42. {
  43. if ( num == vnum )
  44. return;
  45. Clear();
  46. vnum = num;
  47. if ( num < 1 )
  48. return;
  49. //nbor = new DWordTab[vnum];
  50. vis = new BitArray(vnum);
  51. fnum = new int[vnum];
  52. //sel.SetSize(vnum);
  53. }
  54. }
  55. [AddComponentMenu("Modifiers/Relax")]
  56. public class MegaRelax : MegaModifier
  57. {
  58. public float Percent = 0.0f;
  59. public float Decay = 0.0f;
  60. float size;
  61. float per;
  62. public MegaAxis axis;
  63. Matrix4x4 mat = new Matrix4x4();
  64. public override string ModName() { return "Relax"; }
  65. public override string GetHelpURL() { return "?page_id=166"; }
  66. static void FindVertexAngles(Mesh mm, float[] vang)
  67. {
  68. int i;
  69. for ( i = 0; i < mm.vertexCount; i++ )
  70. vang[i] = 0.0f;
  71. int[] tris = mm.triangles;
  72. int[] face = new int[3];
  73. Vector3[] verts = mm.vertices;
  74. for ( i = 0; i < tris.Length; i++ )
  75. {
  76. //int *vv = mm.f[i].vtx;
  77. int deg = 3; //mm.f[i].deg;
  78. face[0] = tris[i];
  79. face[1] = tris[i + 1];
  80. face[2] = tris[i + 2];
  81. for ( int j = 0; j < 3; j++ )
  82. {
  83. Vector3 d1 = verts[face[(j + 1) % deg]] - verts[face[j]];
  84. Vector3 d2 = verts[face[(j + deg - 1) % deg]] - verts[face[j]];
  85. float len = Vector3.SqrMagnitude(d1);
  86. if ( len == 0.0f )
  87. continue;
  88. d1 /= Mathf.Sqrt(len);
  89. len = Vector3.SqrMagnitude(d2);
  90. if ( len == 0.0f )
  91. continue;
  92. d2 /= Mathf.Sqrt(len);
  93. float cs = Vector3.Dot(d1, d2);
  94. // STEVE: What about angles over PI?
  95. if ( cs >= 1.0f )
  96. continue; // angle of 0
  97. if ( cs <= -1.0f )
  98. vang[face[j]] += Mathf.PI;
  99. else
  100. vang[face[j]] += Mathf.Acos(cs);
  101. }
  102. }
  103. }
  104. public float relax = 0.0f;
  105. public int iter = 1;
  106. public bool boundary = false;
  107. public bool saddle = false;
  108. int MAX_ITER = 999999999;
  109. int MIN_ITER = 0;
  110. float MAX_RELAX = 1.0f;
  111. float MIN_RELAX = -1.0f;
  112. void ModifyObject()
  113. {
  114. Matrix4x4 modmat,minv;
  115. float wtdRelax; // mjm - 4.8.99
  116. relax = Mathf.Clamp(relax, MIN_RELAX, MAX_RELAX);
  117. iter = Mathf.Clamp(iter, MIN_ITER, MAX_ITER);
  118. int i, j, max;
  119. DWORD selLevel = mesh->selLevel;
  120. float *vsw = (selLevel!=MESH_OBJECT) ? mesh->getVSelectionWeights() : NULL;
  121. rd->SetVNum (mesh->numVerts);
  122. for ( i = 0; i < rd->vnum; i++ )
  123. {
  124. rd->fnum[i] = 0;
  125. rd->nbor[i].ZeroCount();
  126. }
  127. rd->sel.ClearAll();
  128. DWORD *v;
  129. int k1, k2, origmax;
  130. for ( i = 0; i < mesh->numFaces; i++ )
  131. {
  132. v = mesh->faces[i].v;
  133. for ( j = 0; j < 3; j++ )
  134. {
  135. if ( (selLevel == MESH_FACE) && mesh->faceSel[i] )
  136. rd->sel.Set(v[j]);
  137. if ( (selLevel == MESH_EDGE) && mesh->edgeSel[i * 3 + j] )
  138. rd->sel.Set(v[j]);
  139. if ( (selLevel == MESH_EDGE) && mesh->edgeSel[i * 3 + (j + 2) % 3] )
  140. rd->sel.Set(v[j]);
  141. origmax = max = rd->nbor[v[j]].Count();
  142. rd->fnum[v[j]]++;
  143. for ( k1 = 0; k1 < max; k1++ )
  144. if ( rd->nbor[v[j]][k1] == v[(j + 1) % 3] )
  145. break;
  146. if ( k1 == max )
  147. {
  148. rd->nbor[v[j]].Append(1, v + (j + 1) % 3, 1);
  149. max++;
  150. }
  151. for ( k2 = 0; k2 < max; k2++ )
  152. if ( rd->nbor[v[j]][k2] == v[(j + 2) % 3] )
  153. break;
  154. if ( k2 == max )
  155. {
  156. rd->nbor[v[j]].Append(1, v + (j + 2) % 3, 1);
  157. max++;
  158. }
  159. if ( max > origmax )
  160. rd->vis[v[j]].SetSize(max, TRUE);
  161. if ( mesh->faces[i].getEdgeVis(j) )
  162. rd->vis[v[j]].Set(k1);
  163. else
  164. {
  165. if ( k1 >= origmax )
  166. rd->vis[v[j]].Clear(k1);
  167. }
  168. if ( mesh->faces[i].getEdgeVis((j + 2) % 3) )
  169. rd->vis[v[j]].Set(k2);
  170. else
  171. {
  172. if ( k2 >= origmax )
  173. rd->vis[v[j]].Clear(k2);
  174. }
  175. }
  176. }
  177. if ( selLevel == MESH_VERTEX )
  178. rd->sel = mesh->vertSel;
  179. else
  180. {
  181. if ( selLevel == MESH_OBJECT )
  182. rd->sel.SetAll();
  183. }
  184. Tab<float> vangles;
  185. if ( saddle )
  186. vangles.SetCount(rd->vnum);
  187. Vector3[] hold = new Vector3[rd->vnum];
  188. int act;
  189. for ( int k = 0; k < iter; k++ )
  190. {
  191. for ( i = 0; i < rd->vnum; i++ )
  192. hold[i] = verts[i];
  193. if ( saddle )
  194. mesh->FindVertexAngles(vangles.Addr(0));
  195. for ( i = 0; i < rd->vnum; i++ )
  196. {
  197. if ( (!rd->sel[i] ) && (!vsw || vsw[i] == 0) )
  198. continue;
  199. if ( saddle && (vangles[i] <= 2.0f * Mathf.PI * 0.99999f) )
  200. continue;
  201. max = rd->nbor[i].Count();
  202. if ( boundary && (rd->fnum[i] < max) )
  203. continue;
  204. if ( max < 1 )
  205. continue;
  206. Vector3 avg = Vector3.zero;
  207. for ( j = 0, act = 0; j < max; j++ )
  208. {
  209. if ( !rd->vis[i][j] )
  210. continue;
  211. act++;
  212. avg += hold[rd->nbor[i][j]];
  213. }
  214. if ( act < 1 )
  215. continue;
  216. wtdRelax = (!rd->sel[i]) ? relax * vsw[i] : relax;
  217. sverts[i] = hold[i] * (1.0f - wtdRelax) + avg * wtdRelax / ((float)act);
  218. //triObj->SetPoint(i, hold[i] * (1.0f - wtdRelax) + avg * wtdRelax / ((float)act));
  219. }
  220. }
  221. }
  222. // 514
  223. public override Vector3 Map(int i, Vector3 p)
  224. {
  225. p = tm.MultiplyPoint3x4(p);
  226. float dcy = Mathf.Exp(-Decay * p.magnitude);
  227. float k = ((size / Mathf.Sqrt(p.x * p.x + p.z * p.z) / 2.0f - 1.0f) * per * dcy) + 1.0f;
  228. p.x *= k;
  229. p.z *= k;
  230. return invtm.MultiplyPoint3x4(p);
  231. }
  232. public override bool ModLateUpdate(MegaModContext mc)
  233. {
  234. return Prepare(mc);
  235. }
  236. public void SetTM1()
  237. {
  238. tm = Matrix4x4.identity;
  239. MegaMatrix.RotateZ(ref tm, -gizmoRot.z * Mathf.Deg2Rad);
  240. MegaMatrix.RotateY(ref tm, -gizmoRot.y * Mathf.Deg2Rad);
  241. MegaMatrix.RotateX(ref tm, -gizmoRot.x * Mathf.Deg2Rad);
  242. MegaMatrix.SetTrans(ref tm, gizmoPos + Offset);
  243. invtm = tm.inverse;
  244. }
  245. public override bool Prepare(MegaModContext mc)
  246. {
  247. mat = Matrix4x4.identity;
  248. switch ( axis )
  249. {
  250. case MegaAxis.X: MegaMatrix.RotateZ(ref mat, Mathf.PI * 0.5f); break;
  251. case MegaAxis.Y: MegaMatrix.RotateX(ref mat, -Mathf.PI * 0.5f); break;
  252. case MegaAxis.Z: break;
  253. }
  254. SetAxis(mat);
  255. float xsize = bbox.max.x - bbox.min.x;
  256. float zsize = bbox.max.z - bbox.min.z;
  257. size = (xsize > zsize) ? xsize : zsize;
  258. // Get the percentage to spherify at this time
  259. per = Percent / 100.0f;
  260. return true;
  261. }
  262. }
  263. #endif