MegaFlowMatchShape.cs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828
  1. 
  2. using UnityEngine;
  3. using System.Collections.Generic;
  4. // TODO: Softbody system like Maya, so lattice based (option for voxel) then add effectors like wind, turbelence
  5. #if false
  6. [System.Serializable]
  7. public class VoxMass
  8. {
  9. public VoxMass(Vector3 _p)
  10. {
  11. p = _p;
  12. }
  13. public Vector3 p;
  14. }
  15. [System.Serializable]
  16. public class Link
  17. {
  18. public Link(int _m1, int _m2)
  19. {
  20. m1 = _m1;
  21. m2 = _m2;
  22. }
  23. public int m1;
  24. public int m2;
  25. }
  26. [ExecuteInEditMode]
  27. public class MegaFlowMatchShape : MonoBehaviour
  28. {
  29. public MegaSoft softbody;
  30. public float shrink = 1.0f;
  31. void Start()
  32. {
  33. update = true;
  34. }
  35. void GetTriBounds(Vector3[] verts, int[] tris, int tri, Vector3 min, out int gxs, out int gxe, out int gys, out int gye, out int gzs, out int gze)
  36. {
  37. Vector3 p = verts[tris[tri]];
  38. //Debug.Log("p0 " + p);
  39. //Vector3 min = bounds.min;
  40. gxs = gxe = (int)((p.x - min.x) / CellSize);
  41. gys = gye = (int)((p.y - min.y) / CellSize);
  42. gzs = gze = (int)((p.z - min.z) / CellSize);
  43. for ( int i = 1; i < 3; i++ )
  44. {
  45. p = verts[tris[tri + i]];
  46. //Debug.Log("p" + i + " " + p);
  47. int x = (int)((p.x - min.x) / CellSize);
  48. int y = (int)((p.y - min.y) / CellSize);
  49. int z = (int)((p.z - min.z) / CellSize);
  50. if ( x < gxs ) gxs = x;
  51. if ( x > gxe ) gxe = x;
  52. if ( y < gys ) gys = y;
  53. if ( y > gye ) gye = y;
  54. if ( z < gzs ) gzs = z;
  55. if ( z > gze ) gze = z;
  56. }
  57. }
  58. int GetXCellOld(int[, ,] cells, int x, int y, int z, int dim)
  59. {
  60. for ( int i = x; i < dim; i++ )
  61. {
  62. if ( cells[i, y, z] != 0 )
  63. {
  64. return i;
  65. }
  66. }
  67. return -1; // no cell
  68. }
  69. int GetXCell(int[, ,] cells, int x, int y, int z, int dim)
  70. {
  71. for ( int i = x; i < dim; i++ )
  72. {
  73. if ( cells[i, y, z] != 0 )
  74. {
  75. for ( int j = i + 1; j < dim; j++ )
  76. {
  77. if ( cells[j, y, z] == 0 )
  78. return j - 1;
  79. }
  80. return i;
  81. }
  82. }
  83. return -1; // no cell
  84. }
  85. int GetYCell(int[, ,] cells, int x, int y, int z, int dim)
  86. {
  87. for ( int i = y; i < dim; i++ )
  88. {
  89. if ( cells[x, i, z] != 0 )
  90. {
  91. return i;
  92. }
  93. }
  94. return -1; // no cell
  95. }
  96. int GetZCell(int[, ,] cells, int x, int y, int z, int dim)
  97. {
  98. for ( int i = z; i < dim; i++ )
  99. {
  100. if ( cells[x, y, i] != 0 )
  101. {
  102. return i;
  103. }
  104. }
  105. return -1; // no cell
  106. }
  107. public int[,,] cells;
  108. public int xs = 0;
  109. public int ys = 0;
  110. public int zs = 0;
  111. public Vector3 cellsize = Vector3.one;
  112. public Vector3 origin;
  113. public Mesh basemesh;
  114. public GameObject voxobj;
  115. public bool update = false;
  116. public float CellSize = 1.0f;
  117. public bool Fill = false;
  118. public int masscount = 0;
  119. public int linkcount = 0;
  120. void Update()
  121. {
  122. if ( update )
  123. {
  124. if ( !realtime )
  125. update = false;
  126. CellSize = Mathf.Clamp(CellSize, 0.1f, 1000.0f);
  127. VoxelMesh(gameObject, CellSize, Fill);
  128. masscount = voxmasses.Count;
  129. linkcount = links.Count;
  130. }
  131. RunPhysics(0.01f);
  132. SetMesh();
  133. }
  134. public void RunPhysics(float t)
  135. {
  136. //RebuildWire();
  137. float time = Time.deltaTime;
  138. while ( time > 0.0f )
  139. {
  140. softbody.Update(softbody.timeStep);
  141. time -= softbody.timeStep;
  142. }
  143. softbody.MoveMasses(softbody);
  144. }
  145. void OnDrawGizmosSelected()
  146. {
  147. Display();
  148. }
  149. //public Vector3 Jitter = Vector3.zero;
  150. public bool realtime = true;
  151. void SetMesh()
  152. {
  153. if ( basemesh )
  154. {
  155. // Rebuild verts test
  156. for ( int i = 0; i < barycoords.Length; i++ )
  157. {
  158. BaryCoord bc = barycoords[i];
  159. Vector3 bl = Vector3.Lerp(softbody.masses[bc.m[0]].pos, softbody.masses[bc.m[1]].pos, bc.p.z);
  160. Vector3 tl = Vector3.Lerp(softbody.masses[bc.m[4]].pos, softbody.masses[bc.m[5]].pos, bc.p.z);
  161. Vector3 br = Vector3.Lerp(softbody.masses[bc.m[3]].pos, softbody.masses[bc.m[2]].pos, bc.p.z);
  162. Vector3 tr = Vector3.Lerp(softbody.masses[bc.m[7]].pos, softbody.masses[bc.m[6]].pos, bc.p.z);
  163. Vector3 l = Vector3.Lerp(bl, tl, bc.p.y);
  164. Vector3 r = Vector3.Lerp(br, tr, bc.p.y);
  165. verts[i] = Vector3.Lerp(l, r, bc.p.x);
  166. }
  167. basemesh.vertices = verts;
  168. basemesh.RecalculateNormals();
  169. }
  170. }
  171. public BaryCoord[] barycoords;
  172. int[] tris;
  173. Vector3[] verts;
  174. // We only need to collision with outside masses so any mass not used 6 times, not if a shell
  175. // plus we give external links a different stiffness
  176. // should work from centre of mesh
  177. // Can easily thread this
  178. // We have spring builder in my max destruction soft body so use that
  179. public void VoxelMesh(GameObject obj, float size, bool fill)
  180. {
  181. if ( obj == null )
  182. return;
  183. voxobj = obj;
  184. Mesh mesh = MegaUtils.GetMesh(voxobj);
  185. basemesh = mesh;
  186. tris = mesh.triangles;
  187. verts = mesh.vertices;
  188. Vector3 meshsize = mesh.bounds.size;
  189. xs = Mathf.CeilToInt(meshsize.x / size);
  190. if ( xs == 0 )
  191. xs = 1;
  192. //Debug.Log("ys " + (meshsize.y / size).ToString("0.000"));
  193. ys = Mathf.CeilToInt(meshsize.y / size);
  194. if ( ys == 0 )
  195. ys = 1;
  196. zs = Mathf.CeilToInt(meshsize.z / size);
  197. if ( zs == 0 )
  198. zs = 1;
  199. origin.x = -((float)xs * 0.5f * size); //mesh.bounds.min + Jitter;
  200. origin.y = -((float)ys * 0.5f * size); //mesh.bounds.min + Jitter;
  201. origin.z = -((float)zs * 0.5f * size); //mesh.bounds.min + Jitter;
  202. // So first check all tris against each cell
  203. // first get bounds of tri
  204. // is it quicker to do each tri, get bounds and check those
  205. // or do each cell and check all tris, (can early out on this)
  206. // alloc array to hold cell data
  207. cells = new int[xs, ys, zs];
  208. // Mmmm looks like a lot quicker otherway for 30 verts on a 4x4x4 we loop 4x4x4x30= 1920
  209. // if we do tri and get bounds then a lot quicker could be as low as 30 or 2x2x2x30 = 240
  210. Bounds box = new Bounds();
  211. int gxs,gxe;
  212. int gys,gye;
  213. int gzs,gze;
  214. Vector3 min = Vector3.zero;
  215. Vector3 half = new Vector3(size * 0.5f, size * 0.5f, size * 0.5f);
  216. cellsize = new Vector3(size, size, size);
  217. //Debug.Log("Origin " + origin.ToString("0.000"));
  218. for ( int i = 0; i < tris.Length; i += 3 )
  219. {
  220. // do bounds on tri
  221. GetTriBounds(verts, tris, i, origin, out gxs, out gxe, out gys, out gye, out gzs, out gze);
  222. //Debug.Log("b[" + i + "] " + gxs + " " + gxe + " " + gys + " " + gye + " " + gzs + " " + gze);
  223. //for ( int z = 0; z < zs; z++ )
  224. for ( int z = gzs; z <= gze; z++ )
  225. {
  226. min.z = origin.z + (z * size);
  227. //for ( int y = 0; y < ys; y++ )
  228. for ( int y = gys; y <= gye; y++ )
  229. {
  230. min.y = origin.y + (y * size);
  231. //for ( int x = 0; x < xs; x++ )
  232. for ( int x = gxs; x <= gxe; x++ )
  233. {
  234. min.x = origin.x + (x * size);
  235. box.SetMinMax(min, min + cellsize);
  236. //Debug.Log("box " + box.min.ToString("0.000"));
  237. // build box for cell
  238. if ( AABB_Triangle_Intersection.TriangleBoxOverlap(verts[tris[i]], verts[tris[i + 1]], verts[tris[i + 2]], box) )
  239. {
  240. if ( x < xs && y < ys && z < zs )
  241. cells[x, y, z] = 1;
  242. //Debug.Log("hit " + x + " " + y + " " + z);
  243. }
  244. }
  245. }
  246. }
  247. }
  248. // We should have a shell now, so now to fill line by line
  249. // can do for each axis and combine result (bit per axis) any bit means voxel, this will fill holes
  250. // Fill it, should do for each axis
  251. // could be a bug here here cant assume pen changes state in next block, so for pen down we get
  252. // the first block but we need end of contigous block
  253. if ( fill )
  254. {
  255. for ( int z = 0; z < zs; z++ )
  256. {
  257. for ( int y = 0; y < ys; y++ )
  258. {
  259. int pd = 0;
  260. while ( true ) //x != -1 )
  261. {
  262. // get pen down
  263. pd = GetXCell(cells, pd, y, z, xs);
  264. if ( pd == -1 )
  265. break;
  266. // get pen up
  267. int pu = GetXCell(cells, pd + 1, y, z, xs);
  268. if ( pu == -1 )
  269. break;
  270. for ( int x = pd + 1; x < pu; x++ )
  271. cells[x, y, z] = 2;
  272. pd = pu + 1; // pd is
  273. }
  274. }
  275. }
  276. }
  277. BuildLattice();
  278. // Build bary coords
  279. barycoords = new BaryCoord[verts.Length];
  280. for ( int i = 0; i < verts.Length; i++ )
  281. {
  282. Vector3 p = verts[i];
  283. int x = (int)((p.x - origin.x) / CellSize);
  284. int y = (int)((p.y - origin.y) / CellSize);
  285. int z = (int)((p.z - origin.z) / CellSize);
  286. BaryCoord bc = new BaryCoord();
  287. bc.p.x = (p.x - origin.x - (float)x * CellSize) / CellSize;
  288. bc.p.y = (p.y - origin.y - (float)y * CellSize) / CellSize;
  289. bc.p.z = (p.z - origin.z - (float)z * CellSize) / CellSize;
  290. for ( int c = 0; c < 8; c++ )
  291. {
  292. bc.m[c] = GetMassIndex(x, y, z, c);
  293. }
  294. //bc.m = FindMassIndex(p);
  295. //Debug.Log("[" + i + "] " + x + " " + y + " " + z + " " + p);
  296. barycoords[i] = bc;
  297. }
  298. #if false
  299. // Rebuild verts test
  300. for ( int i = 0; i < barycoords.Length; i++ )
  301. {
  302. BaryCoord bc = barycoords[i];
  303. Vector3 bl = Vector3.Lerp(voxmasses[bc.m[0]].p, voxmasses[bc.m[1]].p, bc.p.z);
  304. Vector3 tl = Vector3.Lerp(voxmasses[bc.m[4]].p, voxmasses[bc.m[5]].p, bc.p.z);
  305. Vector3 br = Vector3.Lerp(voxmasses[bc.m[3]].p, voxmasses[bc.m[2]].p, bc.p.z);
  306. Vector3 tr = Vector3.Lerp(voxmasses[bc.m[7]].p, voxmasses[bc.m[6]].p, bc.p.z);
  307. Vector3 l = Vector3.Lerp(bl, tl, bc.p.y);
  308. Vector3 r = Vector3.Lerp(br, tr, bc.p.y);
  309. verts[i] = Vector3.Lerp(l, r, bc.p.x);
  310. }
  311. #endif
  312. //mesh.vertices = verts;
  313. }
  314. int FindMassIndex(Vector3 p)
  315. {
  316. for ( int i = 0; i < voxmasses.Count; i++ )
  317. {
  318. if ( voxmasses[i].p == p )
  319. return i;
  320. }
  321. return -1;
  322. }
  323. int GetMassIndex(int x, int y, int z, int c)
  324. {
  325. Vector3 p = Vector3.zero;
  326. p.z = origin.z + (z * CellSize);
  327. p.y = origin.y + (y * CellSize);
  328. p.x = origin.x + (x * CellSize);
  329. return FindMassIndex(GetCorner(p, c));
  330. }
  331. [System.Serializable]
  332. public class BaryCoord
  333. {
  334. public int[] m = new int[8];
  335. public Vector3 p;
  336. }
  337. public Color fillcol = Color.red;
  338. public Color edgecol = Color.green;
  339. void Display1()
  340. {
  341. if ( cells == null )
  342. return;
  343. Vector3 pos = Vector3.zero;
  344. Gizmos.matrix = transform.localToWorldMatrix;
  345. Vector3 half = cellsize * 0.5f;
  346. Vector3 org = origin + half; // - Jitter;
  347. // Draw a cubecap for each cell, green for shell red for inside
  348. Gizmos.color = Color.green;
  349. if ( Fill )
  350. {
  351. //Gizmos.color = Color.red;
  352. Color col1 = fillcol;
  353. for ( int z = 0; z < zs; z++ )
  354. {
  355. pos.z = org.z + z * cellsize.z;
  356. col1.r -= 0.01f;
  357. for ( int y = 0; y < ys; y++ )
  358. {
  359. Gizmos.color = fillcol; //col1; //Color.green;
  360. pos.y = org.y + y * cellsize.y;
  361. for ( int x = 0; x < xs; x++ )
  362. {
  363. pos.x = org.x + x * cellsize.x;
  364. int v = cells[x, y, z];
  365. if ( v == 2 )
  366. Gizmos.DrawWireCube(pos, cellsize);
  367. }
  368. }
  369. }
  370. }
  371. Color col = edgecol;
  372. for ( int z = 0; z < zs; z++ )
  373. {
  374. pos.z = org.z + z * cellsize.z;
  375. col.g -= 0.01f;
  376. for ( int y = 0; y < ys; y++ )
  377. {
  378. Gizmos.color = col; //Color.green;
  379. pos.y = org.y + y * cellsize.y;
  380. for ( int x = 0; x < xs; x++ )
  381. {
  382. pos.x = org.x + x * cellsize.x;
  383. int v = cells[x, y, z];
  384. if ( v == 1 )
  385. Gizmos.DrawWireCube(pos, cellsize);
  386. }
  387. }
  388. }
  389. }
  390. void Display()
  391. {
  392. if ( cells == null )
  393. return;
  394. Gizmos.matrix = transform.localToWorldMatrix;
  395. Color col = fillcol; //edgecol;
  396. Gizmos.color = col;
  397. for ( int i = 0; i < links.Count; i++ )
  398. {
  399. //Gizmos.DrawLine(voxmasses[links[i].m1].p, voxmasses[links[i].m2].p);
  400. }
  401. for ( int m = 0; m < softbody.masses.Count; m++ )
  402. {
  403. Vector3 p = softbody.masses[m].pos;
  404. Gizmos.DrawCube(p, cellsize * 0.05f);
  405. }
  406. col = Color.black;
  407. // Draw springs
  408. for ( int s = 0; s < softbody.springs.Count; s++ )
  409. {
  410. Vector3 p1 = softbody.masses[softbody.springs[s].p1].pos;
  411. Vector3 p2 = softbody.masses[softbody.springs[s].p2].pos;
  412. //float len = softbody.springs[s].len;
  413. //float w = ((softbody.springs[s].len - softbody.springs[s].restlen) / softbody.springs[s].restlen);// * softbody.springs[s].ks; //con.springs[s].restlen;
  414. float w = ((Vector3.Distance(p1, p2) - softbody.springs[s].restlen) / softbody.springs[s].restlen); // * softbody.springs[s].ks; //con.springs[s].restlen;
  415. //w /= 0.1f;
  416. if ( w >= 0.0f )
  417. {
  418. float alpha = Mathf.Clamp01(w / 0.01f);
  419. col = Color.Lerp(Color.green, Color.red, alpha);
  420. }
  421. else
  422. {
  423. float alpha = Mathf.Clamp01(-w / 0.01f);
  424. col = Color.Lerp(Color.green, Color.blue, -alpha);
  425. }
  426. col.a = edgecol.a;
  427. Gizmos.color = col;
  428. Gizmos.DrawLine(p1, p2);
  429. }
  430. }
  431. int IsSolid(int x, int y, int z)
  432. {
  433. if ( x >= 0 && y >= 0 && x >= 0 )
  434. {
  435. return cells[x, y, z];
  436. }
  437. return 0;
  438. }
  439. public List<VoxMass> voxmasses = new List<VoxMass>();
  440. public List<Link> links = new List<Link>();
  441. int AddMass(Vector3 p)
  442. {
  443. for ( int i = 0; i < voxmasses.Count; i++ )
  444. {
  445. if ( voxmasses[i].p == p )
  446. return i;
  447. }
  448. voxmasses.Add(new VoxMass(p));
  449. return voxmasses.Count - 1;
  450. }
  451. int AddLink(int m1, int m2)
  452. {
  453. for ( int i = 0; i < links.Count; i++ )
  454. {
  455. if ( links[i].m1 == m1 && links[i].m2 == m2 )
  456. return i;
  457. if ( links[i].m1 == m2 && links[i].m2 == m1 )
  458. return i;
  459. }
  460. links.Add(new Link(m1, m2));
  461. return links.Count - 1;
  462. }
  463. Vector3 GetCorner(Vector3 org, int corner)
  464. {
  465. Vector3 p = org;
  466. switch ( corner )
  467. {
  468. case 0: break; //return org;
  469. case 1: org.z += cellsize.z; break;
  470. case 2: org.z += cellsize.z; org.x += cellsize.x; break;
  471. case 3: org.x += cellsize.x; break;
  472. case 4: org.y += cellsize.y; break; //return org;
  473. case 5: org.y += cellsize.y; org.z += cellsize.z; break;
  474. case 6: org.y += cellsize.y; org.z += cellsize.z; org.x += cellsize.x; break;
  475. case 7: org.y += cellsize.y; org.x += cellsize.x; break;
  476. }
  477. return org;
  478. }
  479. // Can split submeshes or vcol out
  480. // Can have different stiffness for internals, also option to not fill (have single springs)
  481. void BuildLattice()
  482. {
  483. Vector3 pos = Vector3.zero;
  484. Vector3 org = origin;
  485. links.Clear();
  486. voxmasses.Clear();
  487. int[] corners = new int[8];
  488. for ( int z = 0; z < zs; z++ )
  489. {
  490. pos.z = org.z + z * cellsize.z;
  491. for ( int y = 0; y < ys; y++ )
  492. {
  493. pos.y = org.y + y * cellsize.y;
  494. for ( int x = 0; x < xs; x++ )
  495. {
  496. pos.x = org.x + x * cellsize.x;
  497. if ( IsSolid(x, y, z) > 0 )
  498. {
  499. // Add the 8 corner masses and the 12 links
  500. // bot square
  501. for ( int c = 0; c < 8; c++ )
  502. {
  503. Vector3 cp = GetCorner(pos, c) * shrink;
  504. corners[c] = AddMass(cp);
  505. }
  506. // Add colours to show links type
  507. // Bottom
  508. AddLink(corners[0], corners[1]);
  509. AddLink(corners[1], corners[2]);
  510. AddLink(corners[2], corners[3]);
  511. AddLink(corners[3], corners[0]);
  512. // top
  513. AddLink(corners[4], corners[5]);
  514. AddLink(corners[5], corners[6]);
  515. AddLink(corners[6], corners[7]);
  516. AddLink(corners[7], corners[4]);
  517. // Sides
  518. AddLink(corners[0], corners[4]);
  519. AddLink(corners[1], corners[5]);
  520. AddLink(corners[2], corners[6]);
  521. AddLink(corners[3], corners[7]);
  522. // Option to add cross bracing, flag for each type of brace, could add cross grid braces
  523. // Bot brace
  524. #if false
  525. AddLink(corners[0], corners[2]);
  526. AddLink(corners[1], corners[3]);
  527. // Top brace
  528. AddLink(corners[4], corners[6]);
  529. AddLink(corners[5], corners[7]);
  530. // Left brace
  531. AddLink(corners[0], corners[5]);
  532. AddLink(corners[1], corners[4]);
  533. // Back brace
  534. AddLink(corners[1], corners[6]);
  535. AddLink(corners[2], corners[5]);
  536. // Right brace
  537. AddLink(corners[2], corners[7]);
  538. AddLink(corners[3], corners[6]);
  539. // Front brace
  540. AddLink(corners[3], corners[4]);
  541. AddLink(corners[0], corners[7]);
  542. #else
  543. // Cross brace 1
  544. AddLink(corners[0], corners[6]);
  545. AddLink(corners[4], corners[2]);
  546. // Cross brace 2
  547. AddLink(corners[1], corners[7]);
  548. AddLink(corners[5], corners[3]);
  549. #endif
  550. }
  551. }
  552. }
  553. }
  554. // Build softbody
  555. softbody.BuildSoftBody(voxmasses, links);
  556. //Debug.Log("masses " + voxmasses.Count);
  557. //Debug.Log("links " + links.Count);
  558. }
  559. #if false
  560. void BuildSoftBody()
  561. {
  562. if ( masses == null )
  563. masses = new List<MegaWireMass>();
  564. masses.Clear();
  565. float ms = wire.Mass / (float)(wire.points + 1);
  566. for ( int i = 0; i <= wire.points; i++ )
  567. {
  568. float alpha = (float)i / (float)wire.points;
  569. float rn = (Random.value - 0.5f) * 2.0f * (wire.massRand * ms);
  570. float m = rn + ms;
  571. MegaWireMass rm = new MegaWireMass(m, Vector3.Lerp(p1, p2, alpha));
  572. masses.Add(rm);
  573. }
  574. if ( springs == null )
  575. springs = new List<MegaWireSpring>();
  576. springs.Clear();
  577. if ( constraints == null )
  578. constraints = new List<MegaWirePointConstraint>();
  579. if ( lenconstraints == null )
  580. lenconstraints = new List<MegaWireLengthConstraint>();
  581. constraints.Clear();
  582. lenconstraints.Clear();
  583. for ( int i = 0; i < masses.Count - 1; i++ )
  584. {
  585. MegaWireSpring spr = new MegaWireSpring(i, i + 1, wire.spring, wire.damp, this, wire.stretch);
  586. springs.Add(spr);
  587. if ( wire.lengthConstraints )
  588. {
  589. MegaWireLengthConstraint lcon = new MegaWireLengthConstraint(i, i + 1, spr.restlen);
  590. lenconstraints.Add(lcon);
  591. }
  592. }
  593. if ( wire.stiffnessSprings )
  594. {
  595. int gap = 2;
  596. for ( int i = 0; i < masses.Count - gap; i++ )
  597. {
  598. MegaWireSpring spr = new MegaWireSpring(i, i + 2, wire.stiffrate, wire.stiffdamp, this, wire.stretch);
  599. springs.Add(spr);
  600. //float alpha = (float)i / (float)masses.Count;
  601. //MegaWireSpring spr = new MegaWireSpring(i, i + gap, stiffspring * stiffnessCrv.Evaluate(alpha), stiffdamp * stiffnessCrv.Evaluate(alpha), this); //, stretch);
  602. //springs.Add(spr);
  603. //WireLengthConstraint lcon = new WireLengthConstraint(i, i + gap, spr.restlen);
  604. //constraints.Add(lcon);
  605. }
  606. }
  607. // Apply fixed end constraints
  608. MegaWirePointConstraint pcon = new MegaWirePointConstraint(0, start.transform, outOffset);
  609. constraints.Add(pcon);
  610. pcon = new MegaWirePointConstraint(masses.Count - 1, end.transform, inOffset);
  611. constraints.Add(pcon);
  612. masspos = new Vector3[masses.Count + 2];
  613. for ( int i = 0; i < masses.Count; i++ )
  614. masspos[i + 1] = masses[i].pos;
  615. masspos[0] = masses[0].pos - (masses[1].pos - masses[0].pos);
  616. masspos[masspos.Length - 1] = masses[masses.Count - 1].pos + (masses[masses.Count - 1].pos - masses[masses.Count - 2].pos);
  617. }
  618. #endif
  619. float Determinant(Matrix4x4 m)
  620. {
  621. Vector3 r0 = m.GetRow(0);
  622. Vector3 r1 = m.GetRow(1);
  623. Vector3 r2 = m.GetRow(2);
  624. return -(r0.z * r1.y * r2.x) + (r0.y * r1.z * r2.x) + (r0.z * r1.x * r2.y) - (r0.x * r1.z * r2.y) - (r0.y * r1.x * r2.z) + (r0.x * r1.y * r2.z);
  625. }
  626. Vector3 barycentricCoords(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p)
  627. {
  628. Vector3 bc = Vector3.zero;
  629. Vector3 q = p - p3;
  630. Vector4 q0 = p0 - p3;
  631. Vector4 q1 = p1 - p3;
  632. Vector4 q2 = p2 - p3;
  633. Matrix4x4 m = Matrix4x4.identity;
  634. m.SetColumn(0, q0);
  635. m.SetColumn(1, q1);
  636. m.SetColumn(2, q2);
  637. float det = Determinant(m);
  638. m.SetColumn(0, q);
  639. bc.x = Determinant(m);
  640. m.SetColumn(0, q0);
  641. m.SetColumn(1, q);
  642. bc.y = Determinant(m);
  643. m.SetColumn(1, q1);
  644. m.SetColumn(2, q);
  645. bc.z = Determinant(m);
  646. if ( det != 0.0f )
  647. bc /= det;
  648. return bc;
  649. }
  650. }
  651. #endif