MegaAttractorShape.cs 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. using UnityEngine;
  2. public enum MegaAttractType
  3. {
  4. Attract,
  5. Repulse,
  6. Rotate,
  7. }
  8. [AddComponentMenu("Modifiers/Attractor Shape")]
  9. public class MegaAttractorShape : MegaModifier
  10. {
  11. public MegaShape shape;
  12. public int curve;
  13. public MegaAttractType attractType = MegaAttractType.Attract;
  14. public float distance = 0.0f;
  15. public float rotate = 0.0f;
  16. public float force = 0.0f;
  17. public float slide = 0.0f;
  18. public AnimationCurve crv = new AnimationCurve(new Keyframe(0, 0), new Keyframe(1, 1));
  19. public int itercount = 4;
  20. //MegaSpline spline;
  21. int k;
  22. Vector3 tangent;
  23. float alpha;
  24. Vector3 delta;
  25. Vector3 nvp;
  26. Vector3 dir = Vector3.zero;
  27. Matrix4x4 rottm = Matrix4x4.identity;
  28. float slidealpha;
  29. Matrix4x4 swtm;
  30. Matrix4x4 swltm;
  31. Matrix4x4 lwtm;
  32. Matrix4x4 wltm;
  33. public float limit = 1.0f;
  34. float limit2 = 0.0f;
  35. Vector3 shapepos;
  36. public bool flat = true;
  37. public bool splinechanged = true;
  38. public override string ModName() { return "Attractor Shape"; }
  39. public override string GetHelpURL() { return "?page_id=338"; }
  40. public Vector3 FindNearestPointWorld(Vector3 p, int iterations, ref float alpha)
  41. {
  42. return swtm.MultiplyPoint3x4(FindNearestPoint(swltm.MultiplyPoint3x4(p), iterations, ref alpha));
  43. }
  44. float positiveInfinity;
  45. float num2;
  46. //int iterations;
  47. void Start()
  48. {
  49. PrepareShape();
  50. }
  51. public Vector3[] points;
  52. void PrepareShape()
  53. {
  54. if ( points == null || points.Length == 0 )
  55. points = new Vector3[101];
  56. int kt = 0;
  57. int ix = 0;
  58. for ( float i = 0.0f; i <= 1.0f; i += 0.01f )
  59. points[ix++] = shape.splines[curve].Interpolate(i, true, ref kt);
  60. }
  61. void Find(Vector3 p)
  62. {
  63. positiveInfinity = float.PositiveInfinity;
  64. num2 = 0.0f;
  65. //iterations = Mathf.Clamp(itercount, 0, 5);
  66. for ( int i = 0; i < 101; i++ )
  67. {
  68. float a = (float)i / 100.0f;
  69. Vector3 vector = points[i] - p; //shape.splines[curve].Interpolate(i, true, ref kt); // - p; //this.GetPositionOnSpline(i) - p;
  70. float sqrMagnitude = vector.sqrMagnitude;
  71. if ( positiveInfinity > sqrMagnitude )
  72. {
  73. positiveInfinity = sqrMagnitude;
  74. num2 = a;
  75. }
  76. }
  77. }
  78. // Find nearest point
  79. public Vector3 FindNearestPoint(Vector3 p, int iterations, ref float alpha)
  80. {
  81. int kt = 0;
  82. Find(p);
  83. MegaSpline spl = shape.splines[curve];
  84. for ( int j = 0; j < itercount; j++ )
  85. {
  86. float num6 = 0.01f * Mathf.Pow(10.0f, -((float)j));
  87. float num7 = num6 * 0.1f;
  88. for ( float k = Mathf.Clamp01(num2 - num6); k <= Mathf.Clamp01(num2 + num6); k += num7 )
  89. {
  90. Vector3 vector2 = spl.Interpolate(k, true, ref kt) - p;
  91. float num9 = vector2.sqrMagnitude;
  92. if ( positiveInfinity > num9 )
  93. {
  94. positiveInfinity = num9;
  95. num2 = k;
  96. }
  97. }
  98. }
  99. alpha = num2;
  100. return shape.InterpCurve3D(curve, num2, true);
  101. }
  102. Vector3 tp = Vector3.zero;
  103. Vector3 qc = Vector3.zero;
  104. public override Vector3 Map(int i, Vector3 p)
  105. {
  106. p = tm.MultiplyPoint3x4(p);
  107. Vector3 vwp = lwtm.MultiplyPoint3x4(p); //transform.TransformPoint(p);
  108. qc.x = vwp.x - shapepos.x;
  109. qc.y = vwp.y - shapepos.y;
  110. qc.z = vwp.z - shapepos.z;
  111. if ( qc.sqrMagnitude < limit2 )
  112. {
  113. Vector3 splpos = FindNearestPointWorld(vwp, itercount, ref alpha);
  114. if ( attractType == MegaAttractType.Repulse )
  115. {
  116. delta.x = vwp.x - splpos.x;
  117. delta.y = vwp.y - splpos.y;
  118. delta.z = vwp.z - splpos.z;
  119. }
  120. else
  121. {
  122. delta.x = splpos.x - vwp.x;
  123. delta.y = splpos.y - vwp.y;
  124. delta.z = splpos.z - vwp.z;
  125. }
  126. float len = delta.magnitude;
  127. if ( len < distance )
  128. {
  129. float val = distance - len;
  130. float calpha = val / distance;
  131. float cval = crv.Evaluate(calpha);
  132. if ( attractType == MegaAttractType.Attract || attractType == MegaAttractType.Repulse )
  133. {
  134. Vector3 move = delta.normalized * val * cval * force;
  135. if ( attractType == MegaAttractType.Attract )
  136. {
  137. if ( move.magnitude <= len ) // can used squared here?
  138. nvp = wltm.MultiplyPoint3x4(vwp + move);
  139. else
  140. nvp = wltm.MultiplyPoint3x4(splpos);
  141. }
  142. else
  143. nvp = wltm.MultiplyPoint3x4(vwp + move);
  144. }
  145. else
  146. {
  147. float alpha1;
  148. if ( slide >= 0.0f )
  149. alpha1 = alpha + ((1.0f - alpha) * slidealpha) * cval;
  150. else
  151. alpha1 = alpha + (alpha * slidealpha) * cval;
  152. if ( alpha1 < 0.0f )
  153. alpha1 = 0.0f;
  154. else
  155. if ( alpha1 >= 1.0f )
  156. alpha1 = 0.99999f;
  157. Vector3 fwd = swtm.MultiplyPoint3x4(shape.splines[curve].InterpCurve3D(alpha1, true, ref k));
  158. float alpha2 = alpha1 + 0.01f;
  159. if ( alpha1 + 0.01f >= 1.0f )
  160. alpha2 = alpha1 - 0.01f;
  161. Vector3 fwd1 = swtm.MultiplyPoint3x4(shape.splines[curve].InterpCurve3D(alpha2, true, ref k));
  162. if ( alpha + 0.01f < 1.0f )
  163. dir = (fwd - fwd1).normalized;
  164. else
  165. dir = (fwd1 - fwd).normalized;
  166. Vector3 rightVector = Vector3.Cross(delta, dir).normalized;
  167. rottm.SetColumn(0, rightVector);
  168. rottm.SetColumn(1, Vector3.Cross(-rightVector, dir));
  169. rottm.SetColumn(2, dir);
  170. rottm.SetColumn(3, fwd);
  171. float ag = (-90.0f + rotate * val * cval) * Mathf.Deg2Rad;
  172. tp.x = len * Mathf.Cos(ag);
  173. tp.y = len * Mathf.Sin(ag);
  174. tp.z = flat ? 0.0f : p.z;
  175. nvp = rottm.MultiplyPoint3x4(tp);
  176. nvp = wltm.MultiplyPoint3x4(nvp);
  177. }
  178. }
  179. else
  180. nvp = p;
  181. p = nvp;
  182. }
  183. return invtm.MultiplyPoint3x4(p);
  184. }
  185. public override bool ModLateUpdate(MegaModContext mc)
  186. {
  187. return Prepare(mc);
  188. }
  189. public override bool Prepare(MegaModContext mc)
  190. {
  191. if ( shape )
  192. {
  193. if ( splinechanged || points == null || points.Length == 0 )
  194. {
  195. PrepareShape();
  196. splinechanged = false;
  197. }
  198. limit2 = limit * limit;
  199. shapepos = shape.transform.position;
  200. slidealpha = slide * 0.01f;
  201. swtm = shape.transform.localToWorldMatrix;
  202. swltm = shape.transform.worldToLocalMatrix;
  203. lwtm = transform.localToWorldMatrix;
  204. wltm = transform.worldToLocalMatrix;
  205. return true;
  206. }
  207. return false;
  208. }
  209. }