MegaSoftPhysics.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504
  1. 
  2. using UnityEngine;
  3. using System.Collections.Generic;
  4. #if false
  5. [System.Serializable]
  6. public class MegaSoft
  7. {
  8. public Vector3 inOffset = Vector3.zero;
  9. public Vector3 outOffset = Vector3.zero;
  10. public float radius = 0.01f;
  11. public Vector3 windFrc = Vector3.zero;
  12. public Transform start;
  13. public Transform end;
  14. public float WireLength = 0.0f;
  15. //Matrix4x4 wtm;
  16. public List<MegaSoftMass> masses = new List<MegaSoftMass>();
  17. public List<MegaSoftSpring> springs = new List<MegaSoftSpring>();
  18. public List<MegaSoftPointConstraint> constraints = new List<MegaSoftPointConstraint>();
  19. public List<MegaSoftLengthConstraint> lenconstraints = new List<MegaSoftLengthConstraint>();
  20. public Vector3[] masspos;
  21. // Physics/Solver params
  22. public float spring = 10.0f;
  23. public float damp = 1.0f;
  24. public float timeStep = 0.01f;
  25. public float Mass = 1.0f;
  26. public Vector3 gravity = new Vector3(0.0f, -9.81f, 0.0f);
  27. public float airdrag = 0.99f;
  28. public float massRand = 0.0f;
  29. public bool doCollisions = false;
  30. public float floor = 0.0f;
  31. public int points = 10;
  32. public int iters = 4;
  33. public int frameWait = 0;
  34. public int frameNum = 0;
  35. public bool stiffnessSprings = false;
  36. public float stiffrate = 10.0f;
  37. public float stiffdamp = 1.0f;
  38. public bool lengthConstraints = false;
  39. Matrix4x4 wtm;
  40. public MegaSoftSolver verletsolver = new MegaSoftSolverVertlet();
  41. // Should set the sim wake time so it will update correctly
  42. public void SetEndConstraintActive(int index, bool active, float time)
  43. {
  44. if ( active )
  45. {
  46. constraints[index].reactivate = time;
  47. constraints[index].rtime = time;
  48. constraints[index].ps = masses[constraints[index].p1].pos;
  49. }
  50. else
  51. constraints[index].active = active;
  52. }
  53. public void Update(float timeStep)
  54. {
  55. verletsolver.doIntegration1(this, timeStep);
  56. }
  57. // This is for cubic interpolation so dont need
  58. public void MoveMasses(MegaSoft soft)
  59. {
  60. return;
  61. for ( int i = 0; i < masses.Count; i++ )
  62. {
  63. masspos[i + 1] = masses[i].pos;
  64. masses[i].forcec = Vector3.zero;
  65. }
  66. masspos[0] = masses[0].pos - (masses[1].pos - masses[0].pos);
  67. masspos[masspos.Length - 1] = masses[masses.Count - 1].pos + (masses[masses.Count - 1].pos - masses[masses.Count - 2].pos);
  68. }
  69. public float DampingRatio = 1.0f;
  70. public void BuildSoftBody(List<VoxMass> points, List<Link> links)
  71. {
  72. if ( masses == null )
  73. masses = new List<MegaSoftMass>();
  74. masses.Clear();
  75. float ms = Mass / (float)(points.Count + 1);
  76. for ( int i = 0; i < points.Count; i++ )
  77. {
  78. MegaSoftMass rm = new MegaSoftMass(ms, points[i].p);
  79. masses.Add(rm);
  80. }
  81. if ( springs == null )
  82. springs = new List<MegaSoftSpring>();
  83. springs.Clear();
  84. if ( constraints == null )
  85. constraints = new List<MegaSoftPointConstraint>();
  86. if ( lenconstraints == null )
  87. lenconstraints = new List<MegaSoftLengthConstraint>();
  88. constraints.Clear();
  89. lenconstraints.Clear();
  90. float damp1 = (DampingRatio * 0.45f) * (2.0f * Mathf.Sqrt(ms * spring));
  91. Debug.Log("ratio " + DampingRatio + " damp " + damp1);
  92. for ( int i = 0; i < links.Count - 1; i++ )
  93. {
  94. MegaSoftSpring spr = new MegaSoftSpring(links[i].m1, links[i].m2, spring, damp, this, 1.0f); //stretch);
  95. springs.Add(spr);
  96. //if ( lengthConstraints )
  97. //{
  98. //MegaSoftLengthConstraint lcon = new MegaSoftLengthConstraint(links[i].m1, links[i].m2, spr.restlen);
  99. //lenconstraints.Add(lcon);
  100. //}
  101. }
  102. if ( stiffnessSprings )
  103. {
  104. //int gap = 2;
  105. //for ( int i = 0; i < masses.Count - gap; i++ )
  106. //{
  107. // MegaWireSpring spr = new MegaWireSpring(i, i + 2, wire.stiffrate, wire.stiffdamp, this, wire.stretch);
  108. // springs.Add(spr);
  109. //}
  110. }
  111. // Apply fixed end constraints
  112. //MegaWirePointConstraint pcon = new MegaWirePointConstraint(0, start.transform, outOffset);
  113. //constraints.Add(pcon);
  114. //pcon = new MegaWirePointConstraint(masses.Count - 1, end.transform, inOffset);
  115. //constraints.Add(pcon);
  116. masspos = new Vector3[masses.Count + 2];
  117. for ( int i = 0; i < masses.Count; i++ )
  118. masspos[i + 1] = masses[i].pos;
  119. masspos[0] = masses[0].pos - (masses[1].pos - masses[0].pos);
  120. masspos[masspos.Length - 1] = masses[masses.Count - 1].pos + (masses[masses.Count - 1].pos - masses[masses.Count - 2].pos);
  121. }
  122. }
  123. [System.Serializable]
  124. public class MegaSoftConstraint
  125. {
  126. public bool active;
  127. public float reactivate = 0.0f;
  128. public float rtime = 0.0f;
  129. public virtual void Apply(MegaSoft soft)
  130. {
  131. }
  132. }
  133. [System.Serializable]
  134. public class MegaSoftLengthConstraint : MegaSoftConstraint
  135. {
  136. public int p1;
  137. public int p2;
  138. public float length;
  139. Vector3 moveVector = Vector3.zero;
  140. public MegaSoftLengthConstraint(int _p1, int _p2, float _len)
  141. {
  142. p1 = _p1;
  143. p2 = _p2;
  144. length = _len;
  145. active = true;
  146. }
  147. public override void Apply(MegaSoft soft)
  148. {
  149. if ( active )
  150. {
  151. moveVector.x = soft.masses[p2].pos.x - soft.masses[p1].pos.x;
  152. moveVector.y = soft.masses[p2].pos.y - soft.masses[p1].pos.y;
  153. moveVector.z = soft.masses[p2].pos.z - soft.masses[p1].pos.z;
  154. if ( moveVector.x != 0.0f || moveVector.y != 0.0f || moveVector.z != 0.0f )
  155. {
  156. float currentLength = moveVector.magnitude;
  157. float do1 = 1.0f / currentLength;
  158. float l = 0.5f * (currentLength - length) * do1;
  159. moveVector.x *= l;
  160. moveVector.y *= l;
  161. moveVector.z *= l;
  162. soft.masses[p1].pos.x += moveVector.x;
  163. soft.masses[p1].pos.y += moveVector.y;
  164. soft.masses[p1].pos.z += moveVector.z;
  165. soft.masses[p2].pos.x -= moveVector.x;
  166. soft.masses[p2].pos.y -= moveVector.y;
  167. soft.masses[p2].pos.z -= moveVector.z;
  168. }
  169. }
  170. }
  171. }
  172. [System.Serializable]
  173. public class MegaSoftPointConstraint : MegaSoftConstraint
  174. {
  175. public int p1;
  176. public Vector3 offset;
  177. public Transform obj;
  178. public Vector3 ps;
  179. public Vector3 tp;
  180. public MegaSoftPointConstraint(int _p1, Transform trans, Vector3 off)
  181. {
  182. offset = off;
  183. p1 = _p1;
  184. obj = trans;
  185. active = true;
  186. reactivate = 0.0f;
  187. rtime = 0.0f;
  188. }
  189. Vector3 easeInOutSine(Vector3 start, Vector3 end, float value)
  190. {
  191. end -= start;
  192. return -end / 2.0f * (Mathf.Cos(Mathf.PI * value / 1.0f) - 1.0f) + start;
  193. }
  194. public void ReActivate(MegaSoft soft, float t)
  195. {
  196. tp = obj.TransformPoint(offset);
  197. if ( !active )
  198. {
  199. if ( reactivate > 0.0f )
  200. {
  201. reactivate -= 0.01f;
  202. //Vector3 delta = tp - soft.masses[p1].pos;
  203. soft.masses[p1].pos = easeInOutSine(tp, ps, reactivate / rtime);
  204. if ( reactivate < 0.0f )
  205. {
  206. reactivate = 0.0f;
  207. active = true;
  208. }
  209. }
  210. }
  211. }
  212. public override void Apply(MegaSoft soft)
  213. {
  214. if ( active )
  215. soft.masses[p1].pos = tp;
  216. }
  217. }
  218. [System.Serializable]
  219. public class MegaSoftSolver
  220. {
  221. public virtual void doIntegration1(MegaSoft soft, float dt) { }
  222. public virtual void Solve() { }
  223. }
  224. [System.Serializable]
  225. public class MegaSoftSolverVertlet : MegaSoftSolver
  226. {
  227. void doCalculateForces(MegaSoft soft)
  228. {
  229. Vector3 frc = soft.gravity;
  230. frc.x += soft.windFrc.x;
  231. frc.y += soft.windFrc.y;
  232. frc.z += soft.windFrc.z;
  233. for ( int i = 0; i < soft.masses.Count; i++ )
  234. {
  235. soft.masses[i].force.x = (soft.masses[i].mass * frc.x) + soft.masses[i].forcec.x;
  236. soft.masses[i].force.y = (soft.masses[i].mass * frc.y) + soft.masses[i].forcec.y;
  237. soft.masses[i].force.z = (soft.masses[i].mass * frc.z) + soft.masses[i].forcec.z;
  238. }
  239. for ( int i = 0; i < soft.springs.Count; i++ )
  240. soft.springs[i].doCalculateSpringForce(soft);
  241. }
  242. void DoConstraints(MegaSoft soft)
  243. {
  244. for ( int c = 0; c < soft.constraints.Count; c++ )
  245. {
  246. soft.constraints[c].ReActivate(soft, soft.timeStep);
  247. }
  248. for ( int i = 0; i < soft.iters; i++ )
  249. {
  250. for ( int c = 0; c < soft.lenconstraints.Count; c++ )
  251. soft.lenconstraints[c].Apply(soft);
  252. for ( int c = 0; c < soft.constraints.Count; c++ )
  253. soft.constraints[c].Apply(soft);
  254. }
  255. }
  256. #if false
  257. public override void doIntegration1(MegaSoft soft, float dt)
  258. {
  259. doCalculateForces(soft); // Calculate forces, only changes _f
  260. /* Then do correction step by integration with central average (Heun) */
  261. for ( int i = 0; i < soft.masses.Count; i++ )
  262. {
  263. soft.masses[i].last = soft.masses[i].pos;
  264. soft.masses[i].vel += dt * soft.masses[i].force * soft.masses[i].oneovermass;
  265. soft.masses[i].pos += soft.masses[i].vel * dt;
  266. soft.masses[i].vel *= soft.airdrag; //friction;
  267. }
  268. DoConstraints(soft);
  269. //DoCollisions(dt);
  270. if ( soft.doCollisions )
  271. DoCollisions(soft);
  272. }
  273. #else
  274. public override void doIntegration1(MegaSoft soft, float dt)
  275. {
  276. doCalculateForces(soft); // Calculate forces, only changes _f
  277. float t2 = dt * dt;
  278. /* Then do correction step by integration with central average (Heun) */
  279. for ( int i = 0; i < soft.masses.Count; i++ )
  280. {
  281. Vector3 last = soft.masses[i].pos;
  282. soft.masses[i].pos += soft.airdrag * (soft.masses[i].pos - soft.masses[i].last) + soft.masses[i].force * soft.masses[i].oneovermass * t2; // * t;
  283. soft.masses[i].vel = (soft.masses[i].pos - last) / dt;
  284. soft.masses[i].last = last;
  285. }
  286. DoConstraints(soft);
  287. if ( soft.doCollisions )
  288. DoCollisions(soft);
  289. }
  290. #endif
  291. void DoCollisions(MegaSoft soft)
  292. {
  293. for ( int i = 0; i < soft.masses.Count; i++ )
  294. {
  295. if ( soft.masses[i].pos.y < soft.floor )
  296. {
  297. soft.masses[i].pos.y = soft.floor;
  298. float VdotN = Vector3.Dot(Vector3.up, soft.masses[i].vel);
  299. Vector3 Vn = Vector3.up * VdotN;
  300. // CALCULATE Vt
  301. //Vector3 Vt = (rope.masses[i].vel - Vn) * rope.floorfriction;
  302. // SCALE Vn BY COEFFICIENT OF RESTITUTION
  303. Vn *= 0.9f; //rope.bounce;
  304. // SET THE VELOCITY TO BE THE NEW IMPULSE
  305. soft.masses[i].vel = Vn; //Vt - Vn;
  306. soft.masses[i].last = soft.masses[i].pos;
  307. }
  308. }
  309. }
  310. }
  311. [System.Serializable]
  312. public class MegaSoftMass
  313. {
  314. public Vector3 pos;
  315. public Vector3 last;
  316. public Vector3 force;
  317. public Vector3 vel;
  318. public Vector3 posc;
  319. public Vector3 velc;
  320. public Vector3 forcec;
  321. public float mass; // 1.0f normally, set to zero to lock in place
  322. public float oneovermass;
  323. public bool collide;
  324. public MegaSoftMass(float m, Vector3 p)
  325. {
  326. mass = m;
  327. oneovermass = 1.0f / mass;
  328. pos = p;
  329. last = p;
  330. force = Vector3.zero;
  331. vel = Vector3.zero;
  332. }
  333. }
  334. [System.Serializable]
  335. public class MegaSoftSpring
  336. {
  337. public int p1;
  338. public int p2;
  339. public float restlen;
  340. public float initlen;
  341. public float ks;
  342. public float kd;
  343. public float len;
  344. public MegaSoftSpring(int _p1, int _p2, float _ks, float _kd, MegaSoft soft)
  345. {
  346. p1 = _p1;
  347. p2 = _p2;
  348. ks = _ks;
  349. kd = _kd;
  350. restlen = (soft.masses[p1].pos - soft.masses[p2].pos).magnitude; // * stretch;
  351. initlen = restlen;
  352. }
  353. public MegaSoftSpring(int _p1, int _p2, float _ks, float _kd, MegaSoft soft, float stretch)
  354. {
  355. p1 = _p1;
  356. p2 = _p2;
  357. ks = _ks;
  358. kd = _kd;
  359. restlen = (soft.masses[p1].pos - soft.masses[p2].pos).magnitude * stretch;
  360. initlen = restlen;
  361. }
  362. public void doCalculateSpringForce(MegaSoft hose)
  363. {
  364. Vector3 deltaP = hose.masses[p1].pos - hose.masses[p2].pos;
  365. float dist = deltaP.magnitude;
  366. Vector3 dir = deltaP / dist;
  367. Vector3 springForce = -ks * (dist - restlen) * dir;
  368. Vector3 deltaV = hose.masses[p1].vel - hose.masses[p2].vel;
  369. springForce += -kd * Vector3.Dot(deltaV, dir) * dir;
  370. //float Hterm = (dist - restlen) * ks;
  371. len = dist;
  372. //float Dterm = (Vector3.Dot(deltaV, deltaP) * kd) / dist;
  373. //Vector3 springForce = deltaP * (1.0f / dist);
  374. //springForce *= -(Hterm + Dterm);
  375. hose.masses[p1].force.x += springForce.x;
  376. hose.masses[p1].force.y += springForce.y;
  377. hose.masses[p1].force.z += springForce.z;
  378. hose.masses[p2].force.x -= springForce.x;
  379. hose.masses[p2].force.y -= springForce.y;
  380. hose.masses[p2].force.z -= springForce.z;
  381. }
  382. public void doCalculateSpringForce2(MegaSoft hose)
  383. {
  384. Vector3 deltaP = hose.masses[p1].pos - hose.masses[p2].pos;
  385. float dist = deltaP.magnitude;
  386. float Hterm = (dist - restlen) * ks;
  387. Vector3 deltaV = hose.masses[p1].vel - hose.masses[p2].vel;
  388. float Dterm = (Vector3.Dot(deltaV, deltaP) * kd) / dist;
  389. Vector3 springForce = deltaP * (1.0f / dist);
  390. springForce *= -(Hterm + Dterm);
  391. hose.masses[p1].force.x += springForce.x;
  392. hose.masses[p1].force.y += springForce.y;
  393. hose.masses[p1].force.z += springForce.z;
  394. hose.masses[p2].force.x -= springForce.x;
  395. hose.masses[p2].force.y -= springForce.y;
  396. hose.masses[p2].force.z -= springForce.z;
  397. }
  398. public void doCalculateSpringForce1(MegaSoft mod)
  399. {
  400. Vector3 direction = mod.masses[p1].pos - mod.masses[p2].pos;
  401. if ( direction != Vector3.zero )
  402. {
  403. float currLength = direction.magnitude;
  404. direction = direction.normalized;
  405. Vector3 force = -ks * ((currLength - restlen) * direction);
  406. mod.masses[p1].force.x += force.x;
  407. mod.masses[p1].force.y += force.y;
  408. mod.masses[p1].force.z += force.z;
  409. mod.masses[p2].force.x -= force.x;
  410. mod.masses[p2].force.y -= force.y;
  411. mod.masses[p2].force.z -= force.z;
  412. len = currLength;
  413. }
  414. }
  415. }
  416. #endif