MegaFlowEffect.cs 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. using UnityEngine;
  2. public enum MegaFlowAlign
  3. {
  4. None,
  5. Flow,
  6. Object,
  7. }
  8. [AddComponentMenu("MegaFlow/Effect Control")]
  9. //[ExecuteInEditMode]
  10. public class MegaFlowEffect : MonoBehaviour
  11. {
  12. public float mass = 1.0f;
  13. public MegaFlow source;
  14. public Vector3 pos = Vector3.zero;
  15. public Vector3 vel = Vector3.zero;
  16. public float dt = 0.01f;
  17. public float scale = 1.0f;
  18. public float Area = 0.1f;
  19. public float Gravity = 0.0f;
  20. public Vector3 rot = Vector3.zero;
  21. public Vector3 rotspeed = Vector3.zero;
  22. public float reynolds = 20.0f;
  23. public float density = 1.22f;
  24. public int framenum = 0;
  25. public MegaFlowFrame frame;
  26. public float scl;
  27. public int emitindex;
  28. public MegaFlowAlign align = MegaFlowAlign.None;
  29. public Vector3 alignrot = Vector3.zero;
  30. public Gradient gradient;
  31. public bool usegradient = false;
  32. public float speedlow = 0.0f;
  33. public float speedhigh = 1.0f;
  34. Quaternion lastalign = Quaternion.identity;
  35. Material mat;
  36. Renderer rend1;
  37. [ContextMenu("Help")]
  38. public void Help()
  39. {
  40. Application.OpenURL("http://www.west-racing.com/mf/?page_id=5972");
  41. }
  42. public void SetFrame(int f)
  43. {
  44. if ( source )
  45. {
  46. if ( f >= 0 && f < source.frames.Count )
  47. {
  48. frame = source.frames[f];
  49. framenum = f;
  50. }
  51. }
  52. }
  53. void Update()
  54. {
  55. if ( source && source.frames.Count > 0 )
  56. {
  57. framenum = Mathf.Clamp(framenum, 0, source.frames.Count - 1);
  58. frame = source.frames[framenum];
  59. float scl = source.Scale * scale;
  60. Vector3 Fshape = Vector3.zero; // Random force due to particle shape
  61. Vector3 Fgrv = new Vector3(0.0f, -Gravity, 0.0f);
  62. float duration = Time.deltaTime;
  63. pos = transform.position;
  64. bool inbounds = true;
  65. float p = density;
  66. float A = Area;
  67. float Re = reynolds;
  68. float coef = 1.0f * p * A * Mathf.Pow(Re, -0.5f);
  69. Vector3 flowpos = pos; //source.transform.worldToLocalMatrix.MultiplyPoint3x4(pos);
  70. // This should be in source already
  71. //Matrix4x4 offtm = Matrix4x4.TRS((frame.size * 0.5f) + frame.offset, Quaternion.identity, Vector3.one);
  72. //Matrix4x4 tm = offtm * source.transform.worldToLocalMatrix;
  73. //Matrix4x4 invtm = tm.inverse;
  74. Vector3 airvel = Vector3.zero;
  75. while ( duration > 0.0f )
  76. {
  77. //Vector3 airvel = invtm.MultiplyVector(frame.GetGridVel(tm.MultiplyPoint3x4(flowpos), ref inbounds) * scl);
  78. airvel = frame.GetGridVelWorld(flowpos, ref inbounds) * scl; //invtm.MultiplyVector(frame.GetGridVel(tm.MultiplyPoint3x4(flowpos), ref inbounds) * scl);
  79. if ( !inbounds )
  80. {
  81. airvel = new Vector3(scale, 0.0f, 0.0f);
  82. flowpos += vel * dt;
  83. }
  84. else
  85. {
  86. Vector3 tvel = airvel - vel;
  87. float U = tvel.magnitude;
  88. float df = coef * U;
  89. Vector3 dir = tvel.normalized;
  90. Vector3 Fdrag = dir * df;
  91. Vector3 Fp = Fdrag + Fshape + Fgrv;
  92. Vector3 acc = Fp / mass;
  93. vel += acc * dt;
  94. flowpos += vel * dt;
  95. }
  96. duration -= dt;
  97. }
  98. if ( flowpos.y < source.floor )
  99. flowpos.y = source.floor;
  100. transform.position = flowpos; //source.transform.localToWorldMatrix.MultiplyPoint3x4(flowpos);
  101. rot += rotspeed * Time.deltaTime;
  102. Quaternion r = Quaternion.Euler(rot);
  103. Vector3 fdir = flowpos - pos;
  104. switch ( align )
  105. {
  106. case MegaFlowAlign.Flow:
  107. {
  108. r = Quaternion.identity;
  109. Quaternion ar = lastalign;
  110. if ( airvel != Vector3.zero )
  111. ar = Quaternion.LookRotation(airvel) * Quaternion.Euler(alignrot);
  112. r = r * ar;
  113. lastalign = ar;
  114. }
  115. break;
  116. case MegaFlowAlign.Object:
  117. {
  118. r = Quaternion.identity;
  119. Quaternion ar = lastalign;
  120. if ( fdir != Vector3.zero )
  121. ar = Quaternion.LookRotation(fdir) * Quaternion.Euler(alignrot);
  122. r = r * ar;
  123. lastalign = ar;
  124. }
  125. break;
  126. }
  127. #if false
  128. if ( align )
  129. {
  130. r = Quaternion.identity;
  131. Quaternion ar = lastalign;
  132. if ( fdir != Vector3.zero )
  133. ar = Quaternion.LookRotation(flowpos - pos) * Quaternion.Euler(alignrot);
  134. r = r * ar;
  135. lastalign = ar;
  136. }
  137. #endif
  138. transform.rotation = r; //Quaternion.Euler(r); //ot);
  139. if ( usegradient )
  140. {
  141. if ( !mat )
  142. {
  143. Renderer rend = GetComponent<Renderer>();
  144. if ( rend && rend.material )
  145. mat = rend.material;
  146. }
  147. if ( mat )
  148. {
  149. float spd = airvel.magnitude;
  150. float a = Mathf.Clamp01((spd - speedlow) / (speedhigh - speedlow));
  151. mat.color = gradient.Evaluate(a);
  152. }
  153. }
  154. }
  155. if ( rend1 == null )
  156. rend1 = GetComponent<Renderer>();
  157. if ( rend1 && !rend1.enabled )
  158. rend1.enabled = true;
  159. }
  160. }