MegaDeformable.cs 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. using UnityEngine;
  2. using System.Collections.Generic;
  3. // Beta modifier
  4. [AddComponentMenu("Modifiers/Deformable")]
  5. public class MegaDeformable : MegaModifier
  6. {
  7. public override string ModName() { return "Deformable"; }
  8. public override void ModStart(MegaModifiers mc)
  9. {
  10. Vector3 s = mc.mesh.bounds.size;
  11. sizeFactor = Mathf.Min(s.x, s.y, s.z);
  12. if ( mc.mesh.colors != null )
  13. baseColors = mc.mesh.colors;
  14. LoadMap(mc);
  15. }
  16. public override bool ModLateUpdate(MegaModContext mc)
  17. {
  18. return Prepare(mc);
  19. }
  20. public override bool Prepare(MegaModContext mc)
  21. {
  22. if ( offsets == null || offsets.Length != mc.mod.verts.Length )
  23. offsets = new Vector3[mc.mod.verts.Length];
  24. return true;
  25. }
  26. public override MegaModChannel ChannelsReq() { return MegaModChannel.Verts | MegaModChannel.Col; }
  27. public override MegaModChannel ChannelsChanged() { return MegaModChannel.Verts | MegaModChannel.Col; }
  28. public float Hardness = 0.5f; // Impact resistance to calculate amount of deformation applied to the mesh
  29. public bool DeformMeshCollider = true; // Configure if the mesh at collider must also be deformed (only works if a MeshCollider is in use)
  30. public float UpdateFrequency = 0.0f; // Configure the mesh (and mesh collider) update frequency in times per second. 0 for real time (high CPU usage)
  31. public float MaxVertexMov = 0.0f; // Maximum movement allowed for a vertex from its original position (0 means no limit)
  32. public Color32 DeformedVertexColor = Color.gray; // Color to be applied at deformed vertices (only works for shaders that handle vertices colors)
  33. public Texture2D HardnessMap; // Texture to modulate maximum movement allowed (uses alpha channel)
  34. public bool usedecay = false;
  35. public float decay = 0.999f;
  36. public Color[] baseColors; // Backup of original mesh vertices colors
  37. public float sizeFactor; // Size factor of mesh
  38. public float[] map;
  39. public Vector3[] offsets;
  40. public float impactFactor = 0.1f;
  41. public float ColForce = 0.5f;
  42. private void LoadMesh()
  43. {
  44. }
  45. public void LoadMap()
  46. {
  47. MegaModifiers mc = GetComponent<MegaModifyObject>();
  48. if ( mc )
  49. {
  50. LoadMap(mc);
  51. }
  52. }
  53. private void LoadMap(MegaModifiers mc)
  54. {
  55. // Load hardness map
  56. if ( HardnessMap )
  57. {
  58. Vector2[] uvs = mc.mesh.uv;
  59. map = new float[uvs.Length];
  60. for ( int c = 0; c < uvs.Length; c++ )
  61. {
  62. Vector2 uv = uvs[c];
  63. map[c] = HardnessMap.GetPixelBilinear(uv.x, uv.y).a;
  64. }
  65. }
  66. else
  67. map = null;
  68. }
  69. public override void Modify(MegaModifiers mc)
  70. {
  71. // Calc collision force
  72. float colForce = ColForce;//Mathf.Min(1, collision.impactForceSum.sqrMagnitude / 1000);
  73. sizeFactor = mc.bbox.size.magnitude;
  74. // distFactor is the amount of deforming in local coordinates
  75. float distFactor = colForce * (sizeFactor * (impactFactor / Mathf.Max(impactFactor, Hardness)));
  76. // Deform process
  77. if ( colpoints != null )
  78. {
  79. for ( int c = 0; c < colpoints.Length; c++ )
  80. {
  81. ContactPoint contact = colpoints[c];
  82. for ( int i = 0; i < verts.Length; i++ )
  83. {
  84. // Apply deformation only on vertex inside "blast area"
  85. Vector3 vp = verts[i] + offsets[i];
  86. Vector3 p = transform.InverseTransformPoint(contact.point);
  87. float d = (vp - p).sqrMagnitude;
  88. if ( d <= distFactor )
  89. {
  90. // Deformation is the collision normal with local deforming ratio
  91. // Vertices near the impact point must also be more deformed
  92. Vector3 n = transform.InverseTransformDirection(contact.normal * (1.0f - (d / distFactor)) * distFactor);
  93. // Apply hardness map if any
  94. if ( map != null )
  95. n *= 1.0f - map[i];
  96. // Deform vertex
  97. //vertices[i] += n;
  98. offsets[i] += n;
  99. // Apply max vertex movement if configured
  100. // Here the deformed vertex position is just scaled down to keep the best deformation while respecting limits
  101. if ( MaxVertexMov > 0.0f )
  102. {
  103. float max = MaxVertexMov;
  104. n = offsets[i]; //vertices[i] - baseVertices[i];
  105. d = n.magnitude;
  106. if ( d > max )
  107. offsets[i] = (n * (max / d));
  108. // Apply vertex color deformation
  109. // Deform color is applied in proportional amount with vertex distance and max deform
  110. if ( baseColors.Length > 0 )
  111. {
  112. d = (d / MaxVertexMov);
  113. mc.cols[i] = Color.Lerp(baseColors[i], DeformedVertexColor, d);
  114. }
  115. }
  116. else
  117. {
  118. if ( mc.cols.Length > 0 )
  119. {
  120. // Apply vertex color deformation
  121. // Deform color is applied in proportional amount with vertex distance and mesh distance factor
  122. mc.cols[i] = Color.Lerp(baseColors[i], DeformedVertexColor, offsets[i].magnitude / (distFactor * 10.0f));
  123. }
  124. }
  125. }
  126. }
  127. }
  128. }
  129. colpoints = null;
  130. if ( !usedecay )
  131. {
  132. for ( int i = 0; i < verts.Length; i++ )
  133. {
  134. sverts[i].x = verts[i].x + offsets[i].x;
  135. sverts[i].y = verts[i].y + offsets[i].y;
  136. sverts[i].z = verts[i].z + offsets[i].z;
  137. }
  138. }
  139. else
  140. {
  141. for ( int i = 0; i < verts.Length; i++ )
  142. {
  143. offsets[i].x *= decay;
  144. offsets[i].y *= decay;
  145. offsets[i].z *= decay;
  146. sverts[i].x = verts[i].x + offsets[i].x;
  147. sverts[i].y = verts[i].y + offsets[i].y;
  148. sverts[i].z = verts[i].z + offsets[i].z;
  149. }
  150. }
  151. }
  152. // We could find the megamod comp
  153. public void Repair(float repair, MegaModifiers mc)
  154. {
  155. Repair(repair, Vector3.zero, 0.0f, mc);
  156. }
  157. public void Repair(float repair, Vector3 point, float radius, MegaModifiers mc)
  158. {
  159. // Check mesh assigned
  160. if ( (!mc.mesh) ) //|| (!meshFilter) )
  161. return;
  162. // Transform world point to mesh local
  163. point = transform.InverseTransformPoint(point);
  164. // Repairing is done returning vertices position and color to original positions by requested amount
  165. //int i = 0;
  166. for ( int i = 0; i < mc.verts.Length; i++ )
  167. {
  168. // Check for repair inside radius
  169. if ( radius > 0.0f )
  170. {
  171. if ( (point - mc.sverts[i]).magnitude >= radius )
  172. continue;
  173. }
  174. // Repair
  175. Vector3 n = offsets[i]; //vertices[i] - baseVertices[i];
  176. offsets[i] = n * (1.0f - repair);
  177. if ( baseColors.Length > 0 )
  178. mc.cols[i] = Color.Lerp(mc.cols[i], baseColors[i], repair);
  179. }
  180. }
  181. //public bool doDeform = false;
  182. public MegaModifyObject modobj;
  183. ContactPoint[] colpoints;
  184. void OnCollisionEnter(Collision collision)
  185. {
  186. if ( modobj == null )
  187. modobj = GetComponent<MegaModifyObject>();
  188. if ( modobj )
  189. modobj.Enabled = true;
  190. colpoints = collision.contacts;
  191. //doDeform = true;
  192. }
  193. void OnCollisionStay(Collision collision)
  194. {
  195. colpoints = collision.contacts;
  196. //doDeform = true;
  197. }
  198. void OnCollisionExit(Collision collision)
  199. {
  200. if ( modobj )
  201. {
  202. if ( !usedecay )
  203. modobj.Enabled = false;
  204. }
  205. }
  206. }