MegaHose.cs 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068
  1. using UnityEngine;
  2. public enum MegaHoseType
  3. {
  4. Round,
  5. Rectangle,
  6. DSection,
  7. }
  8. // Option for mesh to deform along
  9. public enum MegaHoseSmooth
  10. {
  11. SMOOTHALL,
  12. SMOOTHNONE,
  13. SMOOTHSIDES,
  14. SMOOTHSEGS,
  15. }
  16. [ExecuteInEditMode]
  17. [AddComponentMenu("MegaShapes/Hose")]
  18. [RequireComponent(typeof(MeshFilter)), RequireComponent(typeof(MeshRenderer))]
  19. public class MegaHose : MonoBehaviour
  20. {
  21. public bool freecreate = true;
  22. public bool updatemesh = true;
  23. Matrix4x4 S = Matrix4x4.identity;
  24. const float HalfIntMax = 16383.5f;
  25. const float PIover2 = 1.570796327f;
  26. const float EPSILON = 0.0001f;
  27. public MegaSpline hosespline = new MegaSpline();
  28. Mesh mesh;
  29. public Vector3[] verts = new Vector3[1];
  30. public Vector2[] uvs = new Vector2[1];
  31. public int[] faces = new int[1];
  32. public Vector3[] normals;
  33. public bool optimize = false;
  34. public bool calctangents = false;
  35. public bool recalcCollider = false;
  36. public bool calcnormals = false;
  37. public bool capends = true;
  38. public GameObject custnode2;
  39. public GameObject custnode;
  40. public Vector3 offset = Vector3.zero;
  41. public Vector3 offset1 = Vector3.zero;
  42. public Vector3 rotate = Vector3.zero;
  43. public Vector3 rotate1 = Vector3.zero;
  44. public Vector3 scale = Vector3.one;
  45. public Vector3 scale1 = Vector3.one;
  46. public int endsmethod = 0;
  47. public float noreflength = 1.0f;
  48. public int segments = 45;
  49. public MegaHoseSmooth smooth = MegaHoseSmooth.SMOOTHALL;
  50. public MegaHoseType wiretype = MegaHoseType.Round;
  51. public float rnddia = 0.2f;
  52. public int rndsides = 8;
  53. public float rndrot = 0.0f;
  54. public float rectwidth = 0.2f;
  55. public float rectdepth = 0.2f;
  56. public float rectfillet = 0.0f;
  57. public int rectfilletsides = 0;
  58. public float rectrotangle = 0.0f;
  59. public float dsecwidth = 0.2f;
  60. public float dsecdepth = 0.2f;
  61. public float dsecfillet = 0.0f;
  62. public int dsecfilletsides = 0;
  63. public int dsecrndsides = 4;
  64. public float dsecrotangle = 0.0f;
  65. public bool mapmemapme = true;
  66. public bool flexon = false;
  67. public float flexstart = 0.1f;
  68. public float flexstop = 0.9f;
  69. public int flexcycles = 5;
  70. public float flexdiameter = -0.2f;
  71. public float tension1 = 10.0f;
  72. public float tension2 = 10.0f;
  73. public bool usebulgecurve = false;
  74. public AnimationCurve bulge = new AnimationCurve(new Keyframe(0, 0), new Keyframe(1, 0));
  75. public float bulgeamount = 1.0f;
  76. public float bulgeoffset = 0.0f;
  77. public Vector2 uvscale = Vector2.one;
  78. public bool animatebulge = false;
  79. public float bulgespeed = 0.0f;
  80. public float minbulge = -1.0f;
  81. public float maxbulge = 2.0f;
  82. public bool displayspline = true;
  83. //public bool realtime = true;
  84. bool visible = true;
  85. public bool InvisibleUpdate = false;
  86. public bool dolateupdate = false;
  87. [ContextMenu("Help")]
  88. public void Help()
  89. {
  90. Application.OpenURL("http://www.west-racing.com/mf/?page_id=3436");
  91. }
  92. void Awake()
  93. {
  94. updatemesh = true;
  95. rebuildcross = true;
  96. Rebuild();
  97. }
  98. void Reset()
  99. {
  100. Rebuild();
  101. }
  102. void OnBecameVisible()
  103. {
  104. visible = true;
  105. }
  106. void OnBecameInvisible()
  107. {
  108. visible = false;
  109. }
  110. public void SetEndTarget(int end, GameObject target)
  111. {
  112. if ( end == 0 )
  113. {
  114. custnode = target;
  115. }
  116. else
  117. {
  118. custnode2 = target;
  119. }
  120. updatemesh = true;
  121. }
  122. public void Rebuild()
  123. {
  124. MeshFilter mf = GetComponent<MeshFilter>();
  125. if ( mf != null )
  126. {
  127. Mesh mesh = mf.sharedMesh; //Utils.GetMesh(gameObject);
  128. if ( mesh == null )
  129. {
  130. mesh = new Mesh();
  131. mf.sharedMesh = mesh;
  132. }
  133. if ( mesh != null )
  134. {
  135. BuildMesh();
  136. }
  137. //updatemesh = false;
  138. }
  139. }
  140. void MakeSaveVertex(int NvertsPerRing, int nfillets, int nsides, MegaHoseType wtype)
  141. {
  142. if ( wtype == MegaHoseType.Round )
  143. {
  144. //Debug.Log("Verts " + NvertsPerRing);
  145. float ang = (Mathf.PI * 2.0f) / (float)(NvertsPerRing - 1);
  146. float diar = rnddia;
  147. diar *= 0.5f;
  148. for ( int i = 0; i < NvertsPerRing; i++ )
  149. {
  150. float u = (float)(i + 1) * ang;
  151. SaveVertex[i] = new Vector3(diar * (float)Mathf.Cos(u), diar * (float)Mathf.Sin(u), 0.0f);
  152. }
  153. }
  154. else
  155. {
  156. if ( wtype == MegaHoseType.Rectangle )
  157. {
  158. int savevertcnt = 0;
  159. int qtrverts = 1 + nfillets;
  160. int hlfverts = 2 * qtrverts;
  161. int thrverts = qtrverts + hlfverts;
  162. float Wr = rectwidth * 0.5f;
  163. float Dr = rectdepth * 0.5f;
  164. float Zfr = rectfillet;
  165. if ( Zfr < 0.0f )
  166. Zfr = 0.0f;
  167. if ( nfillets > 0 )
  168. {
  169. float WmZ = Wr - Zfr, DmZ = Dr - Zfr;
  170. float ZmW = -WmZ, ZmD = -DmZ;
  171. SaveVertex[0] = new Vector3(Wr , DmZ, 0.0f);
  172. SaveVertex[nfillets] = new Vector3(WmZ, Dr , 0.0f);
  173. SaveVertex[qtrverts] = new Vector3(ZmW, Dr , 0.0f);
  174. SaveVertex[qtrverts + nfillets] = new Vector3(-Wr, DmZ, 0.0f);
  175. SaveVertex[hlfverts] = new Vector3(-Wr, ZmD, 0.0f);
  176. SaveVertex[hlfverts + nfillets] = new Vector3(ZmW, -Dr, 0.0f);
  177. SaveVertex[thrverts] = new Vector3(WmZ, -Dr, 0.0f);
  178. SaveVertex[thrverts + nfillets] = new Vector3(Wr , ZmD, 0.0f);
  179. if ( nfillets > 1 )
  180. {
  181. float ang = PIover2 / (float)nfillets;
  182. savevertcnt = 1;
  183. for ( int i = 0; i < nfillets - 1; i++ )
  184. {
  185. float u = (float)(i + 1) * ang;
  186. float cu = Zfr * Mathf.Cos(u), su = Zfr * Mathf.Sin(u);
  187. SaveVertex[savevertcnt] = new Vector3(WmZ + cu, DmZ + su, 0.0f);
  188. SaveVertex[savevertcnt + qtrverts] = new Vector3(ZmW - su, DmZ + cu, 0.0f);
  189. SaveVertex[savevertcnt + hlfverts] = new Vector3(ZmW - cu, ZmD - su, 0.0f);
  190. SaveVertex[savevertcnt + thrverts] = new Vector3(WmZ + su, ZmD - cu, 0.0f);
  191. savevertcnt++;
  192. }
  193. }
  194. SaveVertex[SaveVertex.Length - 1] = SaveVertex[0];
  195. }
  196. else
  197. {
  198. if ( smooth == MegaHoseSmooth.SMOOTHNONE )
  199. {
  200. SaveVertex[savevertcnt++] = new Vector3(Wr, Dr, 0.0f);
  201. SaveVertex[savevertcnt++] = new Vector3(-Wr, Dr, 0.0f);
  202. SaveVertex[savevertcnt++] = new Vector3(-Wr, Dr, 0.0f);
  203. SaveVertex[savevertcnt++] = new Vector3(-Wr, -Dr, 0.0f);
  204. SaveVertex[savevertcnt++] = new Vector3(-Wr, -Dr, 0.0f);
  205. SaveVertex[savevertcnt++] = new Vector3(Wr, -Dr, 0.0f);
  206. SaveVertex[savevertcnt++] = new Vector3(Wr, -Dr, 0.0f);
  207. SaveVertex[savevertcnt++] = new Vector3(Wr, Dr, 0.0f);
  208. }
  209. else
  210. {
  211. SaveVertex[savevertcnt++] = new Vector3(Wr, Dr, 0.0f);
  212. SaveVertex[savevertcnt++] = new Vector3(-Wr, Dr, 0.0f);
  213. SaveVertex[savevertcnt++] = new Vector3(-Wr, -Dr, 0.0f);
  214. SaveVertex[savevertcnt++] = new Vector3(Wr, -Dr, 0.0f);
  215. SaveVertex[savevertcnt++] = new Vector3(Wr, Dr, 0.0f);
  216. }
  217. }
  218. }
  219. else
  220. {
  221. int savevertcnt = 0;
  222. float sang = Mathf.PI / (float)nsides;
  223. float Wr = dsecwidth * 0.5f;
  224. float Dr = dsecdepth * 0.5f;
  225. float Zfr = dsecfillet;
  226. if ( Zfr < 0.0f )
  227. Zfr = 0.0f;
  228. float LeftCenter = Dr-Wr;
  229. if ( nfillets > 0 )
  230. {
  231. float DmZ = Dr-Zfr,
  232. ZmD = -DmZ,
  233. WmZ = Wr-Zfr;
  234. int oneqtrverts = 1 + nfillets;
  235. int threeqtrverts = oneqtrverts + 1 + nsides;
  236. SaveVertex[0] = new Vector3(Wr , DmZ, 0.0f);
  237. SaveVertex[nfillets] = new Vector3(WmZ, Dr , 0.0f);
  238. SaveVertex[oneqtrverts] = new Vector3(LeftCenter, Dr, 0.0f);
  239. SaveVertex[oneqtrverts + nsides] = new Vector3(LeftCenter, -Dr, 0.0f);
  240. SaveVertex[threeqtrverts] = new Vector3(WmZ, -Dr , 0.0f);
  241. SaveVertex[threeqtrverts + nfillets] = new Vector3(Wr, ZmD, 0.0f);
  242. if ( nfillets > 1 )
  243. {
  244. float ang = PIover2 / (float)nfillets;
  245. savevertcnt = 1;
  246. for ( int i = 0; i < nfillets - 1; i++ )
  247. {
  248. float u = (float)(i + 1) * ang;
  249. float cu = Zfr * Mathf.Cos(u);
  250. float su = Zfr * Mathf.Sin(u);
  251. SaveVertex[savevertcnt] = new Vector3(WmZ + cu, DmZ + su, 0.0f);
  252. SaveVertex[savevertcnt+threeqtrverts] = new Vector3(WmZ + su, ZmD - cu, 0.0f);
  253. savevertcnt++;
  254. }
  255. }
  256. savevertcnt = 1 + oneqtrverts;
  257. for ( int i = 0; i < nsides - 1; i++ )
  258. {
  259. float u = (float)(i + 1) * sang;
  260. float cu = Dr * Mathf.Cos(u);
  261. float su = Dr * Mathf.Sin(u);
  262. SaveVertex[savevertcnt] = new Vector3(LeftCenter - su, cu, 0.0f);
  263. savevertcnt++;
  264. }
  265. }
  266. else
  267. {
  268. SaveVertex[savevertcnt] = new Vector3(Wr, Dr, 0.0f);
  269. savevertcnt++;
  270. SaveVertex[savevertcnt] = new Vector3(LeftCenter, Dr, 0.0f);
  271. savevertcnt++;
  272. for ( int i = 0; i < nsides - 1; i++ )
  273. {
  274. float u = (float)(i + 1) * sang;
  275. float cu = Dr * Mathf.Cos(u);
  276. float su = Dr * Mathf.Sin(u);
  277. SaveVertex[savevertcnt] = new Vector3(LeftCenter - su, cu, 0.0f);
  278. savevertcnt++;
  279. }
  280. SaveVertex[savevertcnt] = new Vector3(LeftCenter, -Dr, 0.0f);
  281. savevertcnt++;
  282. SaveVertex[savevertcnt] = new Vector3(Wr, -Dr, 0.0f);
  283. savevertcnt++;
  284. }
  285. SaveVertex[SaveVertex.Length - 1] = SaveVertex[0];
  286. }
  287. }
  288. // UVs
  289. float dist = 0.0f;
  290. Vector3 last = Vector3.zero;
  291. for ( int i = 0; i < NvertsPerRing; i++ )
  292. {
  293. if ( i > 0 )
  294. dist += (SaveVertex[i] - last).magnitude;
  295. SaveUV[i] = new Vector2(0.0f, dist * uvscale.y);
  296. last = SaveVertex[i];
  297. }
  298. for ( int i = 0; i < NvertsPerRing; i++ )
  299. SaveUV[i].y /= dist;
  300. float rotangle = 0.0f;
  301. switch ( wtype )
  302. {
  303. case MegaHoseType.Round: rotangle = rndrot; break;
  304. case MegaHoseType.Rectangle: rotangle = rectrotangle; break;
  305. case MegaHoseType.DSection: rotangle = dsecrotangle; break;
  306. }
  307. if ( rotangle != 0.0f )
  308. {
  309. rotangle *= Mathf.Deg2Rad;
  310. float cosu = Mathf.Cos(rotangle);
  311. float sinu = Mathf.Sin(rotangle);
  312. for ( int m = 0; m < NvertsPerRing; m++ )
  313. {
  314. float tempx = SaveVertex[m].x * cosu - SaveVertex[m].y * sinu;
  315. float tempy = SaveVertex[m].x * sinu + SaveVertex[m].y * cosu;
  316. SaveVertex[m].x = tempx;
  317. SaveVertex[m].y = tempy;
  318. }
  319. }
  320. // Normals
  321. if ( calcnormals )
  322. {
  323. for ( int i = 0; i < NvertsPerRing; i++ )
  324. {
  325. int ii = (i + 1) % NvertsPerRing;
  326. Vector3 delta = (SaveVertex[ii] - SaveVertex[i]).normalized;
  327. //SaveNormals[i] = new Vector3(-delta.y, delta.x, 0.0f);
  328. //SaveNormals[i] = new Vector3(-delta.x, delta.y, 0.0f);
  329. //SaveNormals[i] = new Vector3(delta.y, delta.x, 0.0f);
  330. SaveNormals[i] = new Vector3(delta.y, -delta.x, 0.0f);
  331. }
  332. }
  333. }
  334. void FixHoseFillet()
  335. {
  336. float width = rectwidth;
  337. float height = rectdepth;
  338. float fillet = rectfillet;
  339. float hh = 0.5f * Mathf.Abs(height);
  340. float ww = 0.5f * Mathf.Abs(width);
  341. float maxf = (hh > ww ? ww : hh);
  342. if ( fillet > maxf )
  343. rectfillet = maxf;
  344. }
  345. float RND11()
  346. {
  347. float num = Random.Range(0.0f, 32768.0f) - HalfIntMax;
  348. return (num / HalfIntMax);
  349. }
  350. void Mult1X3(Vector3 A, Matrix4x4 B, ref Vector3 C)
  351. {
  352. C[0] = A[0] * B[0, 0] + A[1] * B[0, 1] + A[2] * B[0, 2];
  353. C[1] = A[0] * B[1, 0] + A[1] * B[1, 1] + A[2] * B[1, 2];
  354. C[2] = A[0] * B[2, 0] + A[1] * B[2, 1] + A[2] * B[2, 2];
  355. }
  356. void Mult1X4(Vector4 A, Matrix4x4 B, ref Vector4 C)
  357. {
  358. C[0] = A[0] * B[0, 0] + A[1] * B[0, 1] + A[2] * B[0, 2] + A[3] * B[0, 3];
  359. C[1] = A[0] * B[1, 0] + A[1] * B[1, 1] + A[2] * B[1, 2] + A[3] * B[1, 3];
  360. C[2] = A[0] * B[2, 0] + A[1] * B[2, 1] + A[2] * B[2, 2] + A[3] * B[2, 3];
  361. C[3] = A[0] * B[3, 0] + A[1] * B[3, 1] + A[2] * B[3, 2] + A[3] * B[3, 3];
  362. }
  363. void SetUpRotation(Vector3 Q, Vector3 W, float Theta, ref Matrix4x4 Rq)
  364. {
  365. float ww1,ww2,ww3,w12,w13,w23,CosTheta,SinTheta,MinCosTheta;
  366. Vector3 temp = Vector3.zero;
  367. Matrix4x4 R = Matrix4x4.identity;
  368. ww1 = W[0] * W[0];
  369. ww2 = W[1] * W[1];
  370. ww3 = W[2] * W[2];
  371. w12 = W[0] * W[1];
  372. w13 = W[0] * W[2];
  373. w23 = W[1] * W[2];
  374. CosTheta = Mathf.Cos(Theta);
  375. MinCosTheta = 1.0f - CosTheta;
  376. SinTheta = Mathf.Sin(Theta);
  377. R[0, 0] = ww1 + (1.0f - ww1) * CosTheta;
  378. R[1, 0] = w12 * MinCosTheta + W[2] * SinTheta;
  379. R[2, 0] = w13 * MinCosTheta - W[1] * SinTheta;
  380. R[0, 1] = w12 * MinCosTheta - W[2] * SinTheta;
  381. R[1, 1] = ww2 + (1.0f - ww2) * CosTheta;
  382. R[2, 1] = w23 * MinCosTheta + W[0] * SinTheta;
  383. R[0, 2] = w13 * MinCosTheta + W[1] * SinTheta;
  384. R[1, 2] = w23 * MinCosTheta - W[0] * SinTheta;
  385. R[2, 2] = ww3 + (1.0f - ww3) * CosTheta;
  386. Mult1X3(Q, R, ref temp);
  387. Rq.SetColumn(0, R.GetColumn(0));
  388. Rq.SetColumn(1, R.GetColumn(1));
  389. Rq.SetColumn(2, R.GetColumn(2));
  390. Rq[0, 3] = Q[0] - temp.x;
  391. Rq[1, 3] = Q[1] - temp.y;
  392. Rq[2, 3] = Q[2] - temp.z;
  393. Rq[3, 0] = Rq[3, 1] = Rq[3, 2] = 0.0f;
  394. Rq[3, 3] = 1.0f;
  395. }
  396. void RotateOnePoint(ref Vector3 Pin, Vector3 Q, Vector3 W, float Theta)
  397. {
  398. Matrix4x4 Rq = Matrix4x4.identity;
  399. Vector4 Pout = Vector3.zero;
  400. Vector4 Pby4;
  401. SetUpRotation(Q, W, Theta, ref Rq);
  402. Pby4 = Pin;
  403. Pby4[3] = 1.0f;
  404. Mult1X4(Pby4, Rq, ref Pout);
  405. Pin = Pout;
  406. }
  407. Vector3 endp1 = Vector3.zero;
  408. Vector3 endp2 = Vector3.zero;
  409. Vector3 endr1 = Vector3.zero;
  410. Vector3 endr2 = Vector3.zero;
  411. public Vector3[] SaveVertex;
  412. public Vector2[] SaveUV;
  413. public Vector3[] SaveNormals;
  414. public bool rebuildcross = true;
  415. public int NvertsPerRing = 0;
  416. public int Nverts = 0;
  417. void Update()
  418. {
  419. if ( animatebulge )
  420. {
  421. if ( Application.isPlaying )
  422. bulgeoffset += bulgespeed * Time.deltaTime;
  423. if ( bulgeoffset > maxbulge )
  424. bulgeoffset -= maxbulge - minbulge;
  425. if ( bulgeoffset < minbulge )
  426. bulgeoffset += maxbulge - minbulge;
  427. updatemesh = true;
  428. }
  429. if ( custnode )
  430. {
  431. if ( custnode.transform.position != endp1 )
  432. {
  433. endp1 = custnode.transform.position;
  434. updatemesh = true;
  435. }
  436. if ( custnode.transform.eulerAngles != endr1 )
  437. {
  438. endr1 = custnode.transform.eulerAngles;
  439. updatemesh = true;
  440. }
  441. }
  442. if ( custnode2 )
  443. {
  444. if ( custnode2.transform.position != endp2 )
  445. {
  446. endp2 = custnode2.transform.position;
  447. updatemesh = true;
  448. }
  449. if ( custnode2.transform.eulerAngles != endr2 )
  450. {
  451. endr2 = custnode2.transform.eulerAngles;
  452. updatemesh = true;
  453. }
  454. }
  455. if ( !dolateupdate )
  456. {
  457. if ( visible || InvisibleUpdate )
  458. {
  459. // Check transforms so we dont update unless we have to
  460. if ( updatemesh ) //|| Application.isEditor )
  461. {
  462. updatemesh = false;
  463. BuildMesh();
  464. }
  465. }
  466. }
  467. }
  468. void LateUpdate()
  469. {
  470. if ( dolateupdate )
  471. {
  472. if ( visible || InvisibleUpdate )
  473. {
  474. // Check transforms so we dont update unless we have to
  475. if ( updatemesh ) //|| Application.isEditor )
  476. {
  477. updatemesh = false;
  478. BuildMesh();
  479. }
  480. }
  481. }
  482. }
  483. public Vector3 up = Vector3.up;
  484. Vector3 starty = Vector3.zero;
  485. Vector3 roty = Vector3.zero;
  486. float yangle = 0.0f;
  487. public Matrix4x4 Tlocal = Matrix4x4.identity;
  488. // we only need to build the savevertex and uvs if mesh def changes, else we can keep the uvs
  489. void BuildMesh()
  490. {
  491. if ( !mesh )
  492. {
  493. mesh = GetComponent<MeshFilter>().sharedMesh;
  494. if ( mesh == null )
  495. {
  496. updatemesh = true;
  497. return;
  498. }
  499. }
  500. if ( hosespline.knots.Count == 0 )
  501. {
  502. hosespline.AddKnot(Vector3.zero, Vector3.zero, Vector3.zero);
  503. hosespline.AddKnot(Vector3.zero, Vector3.zero, Vector3.zero);
  504. }
  505. FixHoseFillet();
  506. bool createfree = freecreate;
  507. if ( (!createfree) && ((!custnode) || (!custnode2)) )
  508. createfree = true;
  509. if ( custnode && custnode2 )
  510. createfree = false;
  511. Matrix4x4 mat1,mat2;
  512. float Lf = 0.0f;
  513. Tlocal = Matrix4x4.identity;
  514. Vector3 startvec, endvec, startpoint, endpoint, endy;
  515. starty = Vector3.zero;
  516. roty = Vector3.zero;
  517. yangle = 0.0f;
  518. Vector3 RV = Vector3.zero;
  519. if ( createfree )
  520. Lf = noreflength;
  521. else
  522. {
  523. RV = up; //new Vector3(xtmp, ytmp, ztmp);
  524. mat1 = custnode.transform.localToWorldMatrix;
  525. mat2 = custnode2.transform.localToWorldMatrix;
  526. Matrix4x4 mato1 = Matrix4x4.identity;
  527. Matrix4x4 mato2 = Matrix4x4.identity;
  528. mato1 = Matrix4x4.TRS(offset, Quaternion.Euler(rotate), scale);
  529. mato1 = mato1.inverse;
  530. mato2 = Matrix4x4.TRS(offset1, Quaternion.Euler(rotate1), scale1);
  531. mato2 = mato2.inverse;
  532. S = transform.localToWorldMatrix;
  533. Matrix4x4 mat1NT, mat2NT;
  534. mat1NT = mat1;
  535. mat2NT = mat2;
  536. MegaMatrix.NoTrans(ref mat1NT);
  537. MegaMatrix.NoTrans(ref mat2NT);
  538. Vector3 P1 = mat1.MultiplyPoint(mato1.GetColumn(3));
  539. Vector3 P2 = mat2.MultiplyPoint(mato2.GetColumn(3));
  540. startvec = mat1NT.MultiplyPoint(mato1.GetColumn(2));
  541. endvec = mat2NT.MultiplyPoint(mato2.GetColumn(2));
  542. starty = mat1NT.MultiplyPoint(mato1.GetColumn(1));
  543. endy = mat2NT.MultiplyPoint(mato2.GetColumn(1));
  544. Matrix4x4 SI = S.inverse;
  545. Vector3 P0 = SI.MultiplyPoint(P1);
  546. Matrix4x4 T1 = mat1;
  547. MegaMatrix.NoTrans(ref T1);
  548. Vector3 RVw = T1.MultiplyPoint(RV);
  549. Lf = (P2 - P1).magnitude;
  550. Vector3 Zw;
  551. if ( Lf < 0.01f )
  552. Zw = P1.normalized;
  553. else
  554. Zw = (P2 - P1).normalized;
  555. Vector3 Xw = Vector3.Cross(RVw, Zw).normalized;
  556. Vector3 Yw = Vector3.Cross(Zw, Xw).normalized;
  557. MegaMatrix.NoTrans(ref SI);
  558. Vector3 Xs = SI.MultiplyPoint(Xw);
  559. Vector3 Ys = SI.MultiplyPoint(Yw);
  560. Vector3 Zs = SI.MultiplyPoint(Zw);
  561. Tlocal.SetColumn(0, Xs);
  562. Tlocal.SetColumn(1, Ys);
  563. Tlocal.SetColumn(2, Zs);
  564. MegaMatrix.SetTrans(ref Tlocal, P0);
  565. // move z-axes of end transforms into local frame
  566. Matrix4x4 TlocalInvNT = Tlocal;
  567. MegaMatrix.NoTrans(ref TlocalInvNT);
  568. TlocalInvNT = TlocalInvNT.inverse;
  569. float tenstop = tension1; // * 0.01f;
  570. float tensbot = tension2; // * 0.01f;
  571. startvec = tensbot * (TlocalInvNT.MultiplyPoint(startvec));
  572. endvec = tenstop * (TlocalInvNT.MultiplyPoint(endvec));
  573. starty = TlocalInvNT.MultiplyPoint(starty);
  574. endy = TlocalInvNT.MultiplyPoint(endy);
  575. yangle = Mathf.Acos(Vector3.Dot(starty, endy));
  576. if ( yangle > EPSILON )
  577. roty = Vector3.Cross(starty, endy).normalized;
  578. else
  579. roty = Vector3.zero;
  580. startpoint = Vector3.zero;
  581. endpoint = new Vector3(0.0f, 0.0f, Lf);
  582. hosespline.knots[0].p = startpoint;
  583. hosespline.knots[0].invec = startpoint - startvec;
  584. hosespline.knots[0].outvec = startpoint + startvec;
  585. hosespline.knots[1].p = endpoint;
  586. hosespline.knots[1].invec = endpoint + endvec;
  587. hosespline.knots[1].outvec = endpoint - endvec;
  588. hosespline.CalcLength(); //10);
  589. }
  590. MegaHoseType wtype = wiretype;
  591. int Segs = segments;
  592. if ( Segs < 3 )
  593. Segs = 3;
  594. if ( rebuildcross )
  595. {
  596. rebuildcross = false;
  597. int nfillets = 0;
  598. int nsides = 0;
  599. if ( wtype == MegaHoseType.Round )
  600. {
  601. NvertsPerRing = rndsides;
  602. if ( NvertsPerRing < 3 )
  603. NvertsPerRing = 3;
  604. }
  605. else
  606. {
  607. if ( wtype == MegaHoseType.Rectangle )
  608. {
  609. nfillets = rectfilletsides;
  610. if ( nfillets < 0 )
  611. nfillets = 0;
  612. if ( smooth == MegaHoseSmooth.SMOOTHNONE )
  613. NvertsPerRing = (nfillets > 0 ? 8 + 4 * (nfillets - 1) : 8);
  614. else
  615. NvertsPerRing = (nfillets > 0 ? 8 + 4 * (nfillets - 1) : 4); //4);
  616. }
  617. else
  618. {
  619. nfillets = dsecfilletsides;
  620. if ( nfillets < 0 )
  621. nfillets = 0;
  622. nsides = dsecrndsides;
  623. if ( nsides < 2 )
  624. nsides = 2;
  625. int nsm1 = nsides - 1;
  626. NvertsPerRing = (nfillets > 0 ? 6 + nsm1 + 2 * (nfillets - 1): 4 + nsm1);
  627. }
  628. }
  629. NvertsPerRing++;
  630. int NfacesPerEnd,NfacesPerRing,Nfaces = 0;
  631. //MegaHoseSmooth SMOOTH = smooth;
  632. Nverts = (Segs + 1) * (NvertsPerRing + 1); // + 2;
  633. if ( capends )
  634. Nverts += 2;
  635. NfacesPerEnd = NvertsPerRing;
  636. NfacesPerRing = 6 * NvertsPerRing;
  637. Nfaces = Segs * NfacesPerRing; // + 2 * NfacesPerEnd;
  638. if ( capends )
  639. {
  640. Nfaces += 2 * NfacesPerEnd;
  641. }
  642. if ( SaveVertex == null || SaveVertex.Length != NvertsPerRing )
  643. {
  644. SaveVertex = new Vector3[NvertsPerRing];
  645. SaveUV = new Vector2[NvertsPerRing];
  646. }
  647. if ( calcnormals )
  648. {
  649. if ( SaveNormals == null || SaveNormals.Length != NvertsPerRing )
  650. SaveNormals = new Vector3[NvertsPerRing];
  651. }
  652. MakeSaveVertex(NvertsPerRing, nfillets, nsides, wtype);
  653. if ( verts == null || verts.Length != Nverts )
  654. {
  655. verts = new Vector3[Nverts];
  656. uvs = new Vector2[Nverts];
  657. faces = new int[Nfaces * 3];
  658. }
  659. if ( calcnormals && (normals == null || normals.Length != Nverts) )
  660. normals = new Vector3[Nverts];
  661. }
  662. if ( Nverts == 0 )
  663. return;
  664. bool mapmenow = mapmemapme;
  665. int thisvert = 0;
  666. int last = Nverts - 1;
  667. int last2 = last - 1;
  668. int lastvpr = NvertsPerRing; // - 1;
  669. int maxseg = Segs + 1;
  670. float flexhere;
  671. float dadjust;
  672. float flexlen;
  673. float flex1 = flexstart;
  674. float flex2 = flexstop;
  675. int flexn = flexcycles;
  676. float flexd = flexdiameter;
  677. Vector3 ThisPosition;
  678. Vector3 ThisXAxis, ThisYAxis, ThisZAxis;
  679. Vector2 uv = Vector2.zero;
  680. Matrix4x4 RingTM = Matrix4x4.identity;
  681. Matrix4x4 invRingTM = Matrix4x4.identity;
  682. for ( int i = 0; i < maxseg; i++ )
  683. {
  684. float incr = (float)i / (float)Segs;
  685. if ( createfree )
  686. {
  687. ThisPosition = new Vector3(0.0f, 0.0f, Lf * incr);
  688. ThisXAxis = new Vector3(1.0f, 0.0f, 0.0f);
  689. ThisYAxis = new Vector3(0.0f, 1.0f, 0.0f);
  690. ThisZAxis = new Vector3(0.0f, 0.0f, 1.0f);
  691. }
  692. else
  693. {
  694. int k = 0;
  695. ThisPosition = hosespline.InterpCurve3D(incr, true, ref k);
  696. ThisZAxis = (hosespline.InterpCurve3D(incr + 0.001f, true, ref k) - ThisPosition).normalized;
  697. ThisYAxis = starty;
  698. if ( yangle > EPSILON )
  699. RotateOnePoint(ref ThisYAxis, Vector3.zero, roty, incr * yangle);
  700. ThisXAxis = Vector3.Cross(ThisYAxis, ThisZAxis).normalized;
  701. ThisYAxis = Vector3.Cross(ThisZAxis, ThisXAxis);
  702. }
  703. RingTM.SetColumn(0, ThisXAxis);
  704. RingTM.SetColumn(1, ThisYAxis);
  705. RingTM.SetColumn(2, ThisZAxis);
  706. MegaMatrix.SetTrans(ref RingTM, ThisPosition);
  707. if ( !createfree )
  708. {
  709. RingTM = Tlocal * RingTM;
  710. }
  711. if ( calcnormals )
  712. {
  713. invRingTM = RingTM;
  714. MegaMatrix.NoTrans(ref invRingTM);
  715. //invRingTM = invRingTM.inverse.transpose;
  716. }
  717. if ( (incr > flex1) && (incr < flex2) && flexon )
  718. {
  719. flexlen = flex2 - flex1;
  720. if ( flexlen < 0.01f )
  721. flexlen = 0.01f;
  722. flexhere = (incr - flex1) / flexlen;
  723. float ang = (float)flexn * flexhere * (Mathf.PI * 2.0f) + PIover2;
  724. dadjust = 1.0f + flexd * (1.0f - Mathf.Sin(ang)); //(float)flexn * flexhere * (Mathf.PI * 2.0f) + PIover2));
  725. }
  726. else
  727. dadjust = 0.0f;
  728. if ( usebulgecurve )
  729. {
  730. if ( dadjust == 0.0f )
  731. dadjust = 1.0f + (bulge.Evaluate(incr + bulgeoffset) * bulgeamount);
  732. else
  733. dadjust += bulge.Evaluate(incr + bulgeoffset) * bulgeamount;
  734. }
  735. uv.x = 0.999999f * incr * uvscale.x;
  736. for ( int j = 0; j < NvertsPerRing; j++ )
  737. {
  738. int jj = j; // % NvertsPerRing;
  739. if ( mapmenow )
  740. {
  741. uv.y = SaveUV[jj].y;
  742. uvs[thisvert] = uv; //new Vector2(0.999999f * incr * uvscale.x, SaveUV[jj].y);
  743. }
  744. if ( dadjust != 0.0f )
  745. {
  746. verts[thisvert] = RingTM.MultiplyPoint(dadjust * SaveVertex[jj]);
  747. }
  748. else
  749. {
  750. verts[thisvert] = RingTM.MultiplyPoint(SaveVertex[jj]);
  751. }
  752. if ( calcnormals )
  753. normals[thisvert] = invRingTM.MultiplyPoint(SaveNormals[jj]).normalized; //.MultiplyPoint(-SaveNormals[jj]);
  754. //if ( j == 0 )
  755. //{
  756. // Debug.Log("norm " + normals[thisvert].ToString("0.000") + " save " + SaveNormals[jj].ToString("0.000"));
  757. //}
  758. thisvert++;
  759. }
  760. if ( mapmenow )
  761. {
  762. //uvs[Nverts + i] = new Vector2(0.999999f * incr, 0.999f);
  763. }
  764. if ( capends )
  765. {
  766. if ( i == 0 )
  767. {
  768. verts[last2] = (createfree ? ThisPosition : Tlocal.MultiplyPoint(ThisPosition));
  769. if ( mapmenow )
  770. uvs[last2] = Vector3.zero;
  771. }
  772. else
  773. {
  774. if ( i == Segs )
  775. {
  776. verts[last] = createfree ? ThisPosition : Tlocal.MultiplyPoint(ThisPosition);
  777. if ( mapmenow )
  778. {
  779. uvs[last] = Vector3.zero;
  780. }
  781. }
  782. }
  783. }
  784. }
  785. // Now, set up the faces
  786. int thisface = 0, v1, v2, v3, v4;
  787. v3 = last2;
  788. if ( capends )
  789. {
  790. for ( int i = 0; i < NvertsPerRing - 1; i++ )
  791. {
  792. v1 = i;
  793. v2 = (i < lastvpr ? v1 + 1 : v1 - lastvpr);
  794. //v5 = (i < lastvpr ? v2 : Nverts);
  795. faces[thisface++] = v2;
  796. faces[thisface++] = v1;
  797. faces[thisface++] = v3;
  798. }
  799. }
  800. int ringnum = NvertsPerRing; // + 1;
  801. for ( int i = 0; i < Segs; i++ )
  802. {
  803. for ( int j = 0; j < NvertsPerRing - 1; j++ )
  804. {
  805. v1 = i * ringnum + j;
  806. v2 = v1 + 1; //(j < lastvpr? v1 + 1 : v1 - lastvpr);
  807. v4 = v1 + ringnum;
  808. v3 = v2 + ringnum;
  809. faces[thisface++] = v1;
  810. faces[thisface++] = v2;
  811. faces[thisface++] = v3;
  812. faces[thisface++] = v1;
  813. faces[thisface++] = v3;
  814. faces[thisface++] = v4;
  815. }
  816. }
  817. int basevert = Segs * ringnum; //NvertsPerRing;
  818. v3 = Nverts - 1;
  819. if ( capends )
  820. {
  821. for ( int i = 0; i < NvertsPerRing - 1; i++ )
  822. {
  823. v1 = i + basevert;
  824. v2 = (i < lastvpr? v1 + 1 : v1 - lastvpr);
  825. //v5 = (i < lastvpr? v2 : Nverts + Segs);
  826. faces[thisface++] = v1;
  827. faces[thisface++] = v2;
  828. faces[thisface++] = v3;
  829. }
  830. }
  831. mesh.Clear();
  832. mesh.subMeshCount = 1;
  833. mesh.vertices = verts;
  834. mesh.uv = uvs;
  835. mesh.triangles = faces;
  836. if ( calcnormals )
  837. mesh.normals = normals;
  838. else
  839. mesh.RecalculateNormals();
  840. mesh.RecalculateBounds();
  841. #if UNITY_5_5 || UNITY_5_6 || UNITY_2017 || UNITY_2018 || UNITY_2019 || UNITY_2020
  842. #else
  843. if ( optimize )
  844. mesh.Optimize();
  845. #endif
  846. if ( calctangents )
  847. {
  848. MegaUtils.BuildTangents(mesh);
  849. }
  850. if ( recalcCollider )
  851. {
  852. if ( meshCol == null )
  853. meshCol = GetComponent<MeshCollider>();
  854. if ( meshCol != null )
  855. {
  856. meshCol.sharedMesh = null;
  857. meshCol.sharedMesh = mesh;
  858. //bool con = meshCol.convex;
  859. //meshCol.convex = con;
  860. }
  861. }
  862. }
  863. public void CalcMatrix(ref Matrix4x4 mat, float incr)
  864. {
  865. #if false
  866. Matrix4x4 RingTM = Matrix4x4.identity;
  867. Matrix4x4 invRingTM = Matrix4x4.identity;
  868. int k = 0;
  869. Vector3 ThisPosition = hosespline.InterpCurve3D(incr, true, ref k);
  870. Vector3 ThisZAxis = (hosespline.InterpCurve3D(incr + 0.001f, true, ref k) - ThisPosition).normalized;
  871. Vector3 ThisYAxis = starty;
  872. if ( yangle > EPSILON )
  873. RotateOnePoint(ref ThisYAxis, Vector3.zero, roty, incr * yangle);
  874. Vector3 ThisXAxis = Vector3.Cross(ThisYAxis, ThisZAxis).normalized;
  875. ThisYAxis = Vector3.Cross(ThisZAxis, ThisXAxis);
  876. RingTM.SetColumn(0, ThisXAxis);
  877. RingTM.SetColumn(1, ThisYAxis);
  878. RingTM.SetColumn(2, ThisZAxis);
  879. MegaMatrix.SetTrans(ref RingTM, ThisPosition);
  880. #endif
  881. mat = Tlocal; // * RingTM;
  882. }
  883. MeshCollider meshCol;
  884. static float findmappos(float curpos)
  885. {
  886. float mappos;
  887. return (mappos = ((mappos = curpos) < 0.0f ? 0.0f : (mappos > 1.0f ? 1.0f : mappos)));
  888. }
  889. void DisplayNormals()
  890. {
  891. }
  892. public Vector3 GetPosition(float alpha)
  893. {
  894. Matrix4x4 RingTM = transform.localToWorldMatrix * Tlocal;
  895. int k = 0;
  896. return RingTM.MultiplyPoint(hosespline.InterpCurve3D(alpha, true, ref k));
  897. }
  898. }