MegaPaint.cs 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. using UnityEngine;
  2. using System.Collections.Generic;
  3. public enum MegaFallOff
  4. {
  5. Gauss,
  6. Linear,
  7. Point,
  8. }
  9. public enum MegaPaintMode
  10. {
  11. Add,
  12. Subtract,
  13. Set,
  14. Multiply,
  15. }
  16. [AddComponentMenu("Modifiers/Paint")]
  17. public class MegaPaint : MegaModifier
  18. {
  19. public float radius = 1.0f;
  20. public float amount = 10.0f;
  21. public float decay = 1.0f;
  22. public bool usedecay = false;
  23. public MegaFallOff fallOff = MegaFallOff.Gauss;
  24. public float gaussc = 0.25f;
  25. public bool useAvgNorm = false;
  26. public Vector3 normal = Vector3.up;
  27. public MegaPaintMode mode = MegaPaintMode.Add; // 0 = add 1 = set 2 = mult
  28. bool hadahit = false;
  29. Vector3 relativePoint = Vector3.zero;
  30. List<int> affected = new List<int>();
  31. List<float> distances= new List<float>();
  32. Matrix4x4 mat = new Matrix4x4();
  33. Vector3[] offsets;
  34. Vector3[] normals;
  35. public override string ModName() { return "Paint"; }
  36. public override string GetHelpURL() { return "?page_id=1292"; }
  37. static float LinearFalloff(float distance, float inRadius)
  38. {
  39. return Mathf.Clamp01(1.0f - distance / inRadius);
  40. }
  41. static float PointFalloff(float dist, float inRadius)
  42. {
  43. return -(dist * dist) / (inRadius * inRadius) + 1.0f;
  44. }
  45. static public float GaussFalloff(float v, float c)
  46. {
  47. float e = 2.718281828f;
  48. float a = 1.0f;
  49. float b = 0.5f;
  50. float xb2 = (v - b) * (v - b);
  51. float c2 = 2.0f * c * c;
  52. float g = a * Mathf.Pow(e, -(xb2 / c2));
  53. return g;
  54. }
  55. float Gaussian(float dist, float width)
  56. {
  57. return Mathf.Exp((-dist * dist) / width);
  58. }
  59. void DeformMesh(Vector3 position, float power, float inRadius)
  60. {
  61. if ( hadahit )
  62. {
  63. float sqrRadius = inRadius * inRadius;
  64. // Calculate averaged normal of all surrounding vertices
  65. Vector3 averageNormal = Vector3.zero;
  66. for ( int i = 0; i < verts.Length; i++ )
  67. {
  68. Vector3 p = verts[i];
  69. float sqrMagnitude = (p - position).sqrMagnitude;
  70. if ( sqrMagnitude > sqrRadius )
  71. continue;
  72. affected.Add(i);
  73. float distance = Mathf.Sqrt(sqrMagnitude);
  74. distances.Add(distance);
  75. if ( useAvgNorm )
  76. {
  77. float falloff = LinearFalloff(distance, inRadius);
  78. averageNormal += falloff * normals[i];
  79. }
  80. }
  81. if ( useAvgNorm )
  82. averageNormal = averageNormal.normalized;
  83. else
  84. averageNormal = normal;
  85. // Deform vertices along averaged normal
  86. for ( int j = 0; j < affected.Count; j++ )
  87. {
  88. float falloff = 0.0f;
  89. switch ( fallOff )
  90. {
  91. case MegaFallOff.Gauss: falloff = GaussFalloff(distances[j], inRadius); break;
  92. case MegaFallOff.Point: falloff = PointFalloff(distances[j], inRadius); break;
  93. default: falloff = LinearFalloff(distances[j], inRadius); break;
  94. }
  95. switch ( mode )
  96. {
  97. case MegaPaintMode.Add: offsets[affected[j]] += averageNormal * falloff * power; break;
  98. case MegaPaintMode.Subtract: offsets[affected[j]] -= averageNormal * falloff * power; break;
  99. case MegaPaintMode.Set: offsets[affected[j]] = averageNormal * amount; break;
  100. case MegaPaintMode.Multiply: offsets[affected[j]] = Vector3.Scale(offsets[affected[j]], averageNormal * (1.0f + (falloff * power))); break;
  101. }
  102. }
  103. }
  104. if ( !usedecay )
  105. {
  106. for ( int i = 0; i < verts.Length; i++ )
  107. {
  108. sverts[i].x = verts[i].x + offsets[i].x;
  109. sverts[i].y = verts[i].y + offsets[i].y;
  110. sverts[i].z = verts[i].z + offsets[i].z;
  111. }
  112. }
  113. else
  114. {
  115. for ( int i = 0; i < verts.Length; i++ )
  116. {
  117. offsets[i].x *= decay;
  118. offsets[i].y *= decay;
  119. offsets[i].z *= decay;
  120. sverts[i].x = verts[i].x + offsets[i].x;
  121. sverts[i].y = verts[i].y + offsets[i].y;
  122. sverts[i].z = verts[i].z + offsets[i].z;
  123. }
  124. }
  125. }
  126. public override void Modify(MegaModifiers mc)
  127. {
  128. DeformMesh(relativePoint, amount * Time.deltaTime, radius);
  129. }
  130. public override Vector3 Map(int i, Vector3 p)
  131. {
  132. return p;
  133. }
  134. public override bool ModLateUpdate(MegaModContext mc)
  135. {
  136. return Prepare(mc);
  137. }
  138. Collider mycollider;
  139. public override bool Prepare(MegaModContext mc)
  140. {
  141. if ( mycollider == null )
  142. {
  143. mycollider = GetComponent<Collider>();
  144. }
  145. affected.Clear();
  146. distances.Clear();
  147. if ( offsets == null || offsets.Length != mc.mod.verts.Length )
  148. {
  149. offsets = new Vector3[mc.mod.verts.Length];
  150. }
  151. normals = mc.mod.mesh.normals; // get current normals
  152. mat = Matrix4x4.identity;
  153. SetAxis(mat);
  154. hadahit = false;
  155. if ( Input.GetMouseButton(0) )
  156. {
  157. RaycastHit hit;
  158. Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
  159. if ( Physics.Raycast(ray, out hit) )
  160. {
  161. if ( hit.collider == mycollider )
  162. {
  163. hadahit = true;
  164. relativePoint = hit.collider.transform.InverseTransformPoint(hit.point);
  165. }
  166. }
  167. }
  168. else
  169. {
  170. }
  171. return true;
  172. }
  173. public override void PrepareMT(MegaModifiers mc, int cores)
  174. {
  175. }
  176. public override void DoWork(MegaModifiers mc, int index, int start, int end, int cores)
  177. {
  178. if ( index == 0 )
  179. Modify(mc);
  180. }
  181. }