MegaModifiers.cs 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353
  1. using UnityEngine;
  2. using System;
  3. using System.Collections.Generic;
  4. #if !UNITY_FLASH && !UNITY_PS3 && !UNITY_METRO && !UNITY_WP8
  5. using System.Threading;
  6. #endif
  7. #if UNITY_EDITOR
  8. using UnityEditor;
  9. #endif
  10. // Do we put verts in here
  11. public struct MegaModContext
  12. {
  13. public MegaBox3 bbox;
  14. public Vector3 Offset;
  15. public MegaModifiers mod;
  16. public GameObject go;
  17. }
  18. public enum MegaJobType
  19. {
  20. Modifier,
  21. FaceNormalCalc,
  22. VertexNormalCalc,
  23. FaceTangentCalc,
  24. VertexTangentCalc,
  25. }
  26. public enum MegaNormalMethod
  27. {
  28. Unity,
  29. Mega,
  30. }
  31. [System.Serializable]
  32. public class MegaNormMap
  33. {
  34. public int[] faces;
  35. }
  36. #if !UNITY_FLASH && !UNITY_PS3 && !UNITY_METRO && !UNITY_WP8
  37. public class MegaTaskInfo
  38. {
  39. public string name;
  40. public volatile int start;
  41. public volatile int end;
  42. public AutoResetEvent pauseevent;
  43. public Thread _thread;
  44. public MegaModContext modcontext;
  45. public int index;
  46. public int cores;
  47. public MegaJobType jobtype;
  48. }
  49. #endif
  50. public enum MegaUpdateMode
  51. {
  52. Update,
  53. LateUpdate,
  54. OnRender,
  55. }
  56. // Collision mesh if a proxy added as a target
  57. // Selection sets might be handy
  58. public class MegaModifiers : MonoBehaviour
  59. {
  60. [HideInInspector]
  61. public Bounds bbox = new Bounds();
  62. public bool recalcnorms = true;
  63. public MegaNormalMethod NormalMethod = MegaNormalMethod.Mega;
  64. public bool recalcbounds = false;
  65. public bool recalcCollider = false;
  66. public bool recalcTangents = false;
  67. public bool dynamicMesh = false;
  68. public bool Enabled = true;
  69. //public bool DoLateUpdate = false;
  70. public MegaUpdateMode UpdateMode = MegaUpdateMode.Update;
  71. //public bool GrabVerts = false;
  72. public bool DrawGizmos = true;
  73. [HideInInspector]
  74. public Vector3[] verts;
  75. [HideInInspector]
  76. public Vector3[] sverts;
  77. [HideInInspector]
  78. public Vector2[] uvs;
  79. [HideInInspector]
  80. public Vector2[] suvs;
  81. [HideInInspector]
  82. public Mesh mesh;
  83. [HideInInspector]
  84. public MegaModifier[] mods = null;
  85. [HideInInspector]
  86. public int UpdateMesh = 0;
  87. [HideInInspector]
  88. public MegaModChannel dirtyChannels;
  89. [HideInInspector]
  90. public GameObject sourceObj;
  91. [HideInInspector]
  92. public Color[] cols;
  93. [HideInInspector]
  94. public float[] selection;
  95. [HideInInspector]
  96. public List<GameObject> group = new List<GameObject>();
  97. public static bool GlobalDisplay = true;
  98. Vector4[] tangents;
  99. Vector3[] tan1;
  100. Vector3[] tan2;
  101. public MegaModContext modContext = new MegaModContext();
  102. public void InitVertSource()
  103. {
  104. VertsSource = true;
  105. UVsSource = true;
  106. }
  107. public Vector3[] GetSourceVerts(MegaModifierTarget target)
  108. {
  109. if ( VertsSource )
  110. {
  111. VertsSource = false;
  112. return target.verts;
  113. }
  114. return target.sverts;
  115. }
  116. public Vector3[] GetDestVerts(MegaModifierTarget target)
  117. {
  118. return target.sverts;
  119. }
  120. public Vector3[] GetSourceVerts()
  121. {
  122. if ( VertsSource )
  123. {
  124. VertsSource = false;
  125. return verts;
  126. }
  127. return sverts;
  128. }
  129. public void ChangeSourceVerts()
  130. {
  131. if ( VertsSource )
  132. VertsSource = false;
  133. }
  134. public Vector3[] GetDestVerts()
  135. {
  136. return sverts;
  137. }
  138. public Vector2[] GetSourceUvs()
  139. {
  140. if ( UVsSource )
  141. {
  142. UVsSource = false;
  143. return uvs;
  144. }
  145. return suvs;
  146. }
  147. public Vector2[] GetDestUvs()
  148. {
  149. return suvs;
  150. }
  151. private static int CompareOrder(MegaModifier m1, MegaModifier m2)
  152. {
  153. return m1.Order - m2.Order;
  154. }
  155. //void Reset()
  156. //{
  157. //ReStart();
  158. //}
  159. #if false
  160. void Start()
  161. {
  162. Debug.Log("Mod STart");
  163. ReStart();
  164. }
  165. // Call if base mesh changes
  166. public void ReStart()
  167. {
  168. mesh = MegaUtils.GetMesh(gameObject);
  169. if ( mesh != null )
  170. {
  171. bbox = mesh.bounds;
  172. sverts = new Vector3[mesh.vertexCount];
  173. verts = mesh.vertices;
  174. uvs = mesh.uv;
  175. suvs = new Vector2[mesh.uv.Length];
  176. cols = mesh.colors;
  177. mods = GetComponents<MegaModifier>();
  178. Array.Sort(mods, CompareOrder);
  179. for ( int i = 0; i < mods.Length; i++ )
  180. {
  181. if ( mods[i] != null )
  182. mods[i].ModStart(this); // Some mods like push error if we dont do this, put in error check and disable
  183. }
  184. }
  185. UpdateMesh = -1;
  186. }
  187. #endif
  188. bool VertsSource = false;
  189. bool UVsSource = false;
  190. public void UpdateCols(int first, Color[] newcols)
  191. {
  192. if ( cols == null || cols.Length == 0 )
  193. cols = new Color[verts.Length];
  194. int end = first + newcols.Length;
  195. if ( end > cols.Length )
  196. end = cols.Length;
  197. int ix = 0;
  198. for ( int i = first; i < end; i++ )
  199. {
  200. cols[i] = newcols[ix++];
  201. }
  202. }
  203. public void UpdateCol(int i, Color col)
  204. {
  205. if ( cols == null || cols.Length == 0 )
  206. cols = new Color[verts.Length];
  207. if ( i < cols.Length )
  208. cols[i] = col;
  209. }
  210. public void UpdateCols(Color[] newcols)
  211. {
  212. if ( cols == null || cols.Length == 0 )
  213. cols = new Color[verts.Length];
  214. if ( newcols.Length != verts.Length )
  215. {
  216. Debug.Log("Number of new Colors does not match vertex count for mesh!");
  217. return;
  218. }
  219. cols = newcols;
  220. }
  221. public void ModifyObject()
  222. {
  223. if ( Enabled && mods != null )
  224. {
  225. dirtyChannels = MegaModChannel.None;
  226. //if ( GrabVerts )
  227. //{
  228. //if ( sverts.Length < mesh.vertexCount )
  229. //sverts = new Vector3[mesh.vertexCount];
  230. //verts = mesh.vertices;
  231. //}
  232. VertsSource = true;
  233. UVsSource = true;
  234. modContext.mod = this;
  235. selection = null;
  236. for ( int i = 0; i < mods.Length; i++ )
  237. {
  238. MegaModifier mod = mods[i];
  239. if ( mod != null && mod.ModEnabled )
  240. {
  241. // **group**
  242. if ( mod.instance )
  243. {
  244. // Actually dont even do this have a GetValues method
  245. mod.SetValues(mod.instance);
  246. }
  247. if ( (mod.ChannelsReq() & MegaModChannel.Verts) != 0 ) // should be changed
  248. {
  249. mod.verts = GetSourceVerts();
  250. mod.sverts = GetDestVerts();
  251. }
  252. modContext.Offset = mod.Offset;
  253. modContext.bbox = mod.bbox;
  254. mod.SetTM();
  255. if ( mod.ModLateUpdate(modContext) )
  256. {
  257. if ( selection != null )
  258. {
  259. mod.ModifyWeighted(this);
  260. if ( UpdateMesh < 1 )
  261. UpdateMesh = 1;
  262. }
  263. else
  264. {
  265. if ( UpdateMesh < 1 )
  266. {
  267. mod.Modify(this);
  268. UpdateMesh = 1;
  269. }
  270. else
  271. {
  272. mod.Modify(this);
  273. }
  274. }
  275. dirtyChannels |= mod.ChannelsChanged();
  276. mod.ModEnd(this);
  277. }
  278. }
  279. }
  280. if ( UpdateMesh == 1 )
  281. {
  282. SetMesh(ref sverts);
  283. UpdateMesh = 0;
  284. }
  285. else
  286. {
  287. if ( UpdateMesh == 0 )
  288. {
  289. SetMesh(ref verts);
  290. UpdateMesh = -1; // Dont need to set verts again until a mod is enabled
  291. }
  292. }
  293. }
  294. }
  295. MeshCollider meshCol = null;
  296. public void SetMesh(ref Vector3[] _verts)
  297. {
  298. if ( mesh == null )
  299. return;
  300. // Force system to use the PS3 remapping method
  301. //if ( true ) //Application.platform == RuntimePlatform.PS3 && !Application.isEditor )
  302. //{
  303. // SetPS3Mesh();
  304. // return;
  305. //}
  306. if ( (dirtyChannels & MegaModChannel.Verts) != 0 )
  307. mesh.vertices = sverts; //_verts; // mesh.vertices = GetVerts(true);
  308. if ( (dirtyChannels & MegaModChannel.UV) != 0 )
  309. mesh.uv = suvs; //GetUVs(true);
  310. if ( recalcnorms )
  311. RecalcNormals();
  312. if ( recalcTangents )
  313. BuildTangents();
  314. if ( recalcbounds )
  315. mesh.RecalculateBounds();
  316. if ( recalcCollider )
  317. {
  318. if ( meshCol == null )
  319. meshCol = GetComponent<MeshCollider>();
  320. if ( meshCol != null )
  321. {
  322. meshCol.sharedMesh = null;
  323. meshCol.sharedMesh = mesh;
  324. }
  325. }
  326. }
  327. public void RecalcNormals()
  328. {
  329. if ( NormalMethod == MegaNormalMethod.Unity || dynamicMesh ) //|| mapping == null )
  330. mesh.RecalculateNormals();
  331. else
  332. {
  333. if ( mapping == null || mapping.Length == 0 )
  334. BuildNormalMapping(mesh, false);
  335. #if UNITY_FLASH || UNITY_PS3 || UNITY_METRO || UNITY_WP8
  336. RecalcNormals(mesh, sverts);
  337. #else
  338. if ( !UseThreading || !ThreadingOn || Cores < 1 || !Application.isPlaying )
  339. RecalcNormals(mesh, sverts);
  340. else
  341. RecalcNormalsMT(mesh, sverts);
  342. #endif
  343. }
  344. }
  345. // Can thread this
  346. void BuildTangents()
  347. {
  348. if ( uvs == null )
  349. return;
  350. BuildTangents(mesh, sverts);
  351. }
  352. void BuildTangents(Mesh ms, Vector3[] _verts)
  353. {
  354. int triangleCount = ms.triangles.Length;
  355. int vertexCount = _verts.Length;
  356. if ( tan1 == null || tan1.Length != vertexCount )
  357. tan1 = new Vector3[vertexCount];
  358. if ( tan2 == null || tan2.Length != vertexCount )
  359. tan2 = new Vector3[vertexCount];
  360. if ( tangents == null || tangents.Length != vertexCount )
  361. tangents = new Vector4[vertexCount];
  362. Vector3[] norms = ms.normals;
  363. int[] tris = ms.triangles;
  364. for ( int a = 0; a < triangleCount; a += 3 )
  365. {
  366. long i1 = tris[a];
  367. long i2 = tris[a + 1];
  368. long i3 = tris[a + 2];
  369. Vector3 v1 = _verts[i1];
  370. Vector3 v2 = _verts[i2];
  371. Vector3 v3 = _verts[i3];
  372. Vector2 w1 = uvs[i1];
  373. Vector2 w2 = uvs[i2];
  374. Vector2 w3 = uvs[i3];
  375. float x1 = v2.x - v1.x;
  376. float x2 = v3.x - v1.x;
  377. float y1 = v2.y - v1.y;
  378. float y2 = v3.y - v1.y;
  379. float z1 = v2.z - v1.z;
  380. float z2 = v3.z - v1.z;
  381. float s1 = w2.x - w1.x;
  382. float s2 = w3.x - w1.x;
  383. float t1 = w2.y - w1.y;
  384. float t2 = w3.y - w1.y;
  385. float r = 1.0f / (s1 * t2 - s2 * t1);
  386. Vector3 sdir = new Vector3((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r);
  387. Vector3 tdir = new Vector3((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r);
  388. tan1[i1].x += sdir.x;
  389. tan1[i1].y += sdir.y;
  390. tan1[i1].z += sdir.z;
  391. tan1[i2].x += sdir.x;
  392. tan1[i2].y += sdir.y;
  393. tan1[i2].z += sdir.z;
  394. tan1[i3].x += sdir.x;
  395. tan1[i3].y += sdir.y;
  396. tan1[i3].z += sdir.z;
  397. tan2[i1].x += tdir.x;
  398. tan2[i1].y += tdir.y;
  399. tan2[i1].z += tdir.z;
  400. tan2[i2].x += tdir.x;
  401. tan2[i2].y += tdir.y;
  402. tan2[i2].z += tdir.z;
  403. tan2[i3].x += tdir.x;
  404. tan2[i3].y += tdir.y;
  405. tan2[i3].z += tdir.z;
  406. }
  407. for ( int a = 0; a < _verts.Length; a++ )
  408. {
  409. Vector3 n = norms[a];
  410. Vector3 t = tan1[a];
  411. Vector3.OrthoNormalize(ref n, ref t);
  412. tangents[a].x = t.x;
  413. tangents[a].y = t.y;
  414. tangents[a].z = t.z;
  415. tangents[a].w = (Vector3.Dot(Vector3.Cross(n, t), tan2[a]) < 0.0f) ? -1.0f : 1.0f;
  416. }
  417. ms.tangents = tangents;
  418. }
  419. public void Sort()
  420. {
  421. Array.Sort(mods, CompareOrder);
  422. }
  423. // Call if you change a priority or externally add a mod
  424. public void BuildList()
  425. {
  426. mods = GetComponents<MegaModifier>();
  427. for ( int i = 0; i < mods.Length; i++ )
  428. {
  429. if ( mods[i].Order == -1 )
  430. mods[i].Order = i;
  431. }
  432. Array.Sort(mods, CompareOrder);
  433. }
  434. #if false
  435. public MegaModifier Add(Type type)
  436. {
  437. MegaModifier mod = (MegaModifier)gameObject.AddComponent(type);
  438. if ( mod != null )
  439. BuildList();
  440. return mod;
  441. }
  442. public static MegaModifiers Get(GameObject go)
  443. {
  444. MegaModifiers mod = (MegaModifiers)go.GetComponent<MegaModifiers>();
  445. if ( mod == null )
  446. mod = go.AddComponent<MegaModifiers>();
  447. return mod;
  448. }
  449. #endif
  450. void OnDrawGizmosSelected()
  451. {
  452. modContext.mod = this;
  453. modContext.go = gameObject;
  454. if ( GlobalDisplay && DrawGizmos && Enabled )
  455. {
  456. for ( int i = 0; i < mods.Length; i++ )
  457. {
  458. MegaModifier mod = mods[i];
  459. if ( mod != null )
  460. {
  461. if ( mod.ModEnabled && mod.DisplayGizmo )
  462. {
  463. modContext.Offset = mod.Offset;
  464. modContext.bbox = mod.bbox;
  465. mod.DrawGizmo(modContext);
  466. }
  467. }
  468. }
  469. }
  470. }
  471. // Multithreaded test
  472. public static bool ThreadingOn;
  473. public bool UseThreading = true;
  474. public static int Cores = 0; //SystemInfo.processorCount; // 0 is not mt
  475. #if !UNITY_FLASH && !UNITY_PS3 && !UNITY_METRO && !UNITY_WP8
  476. static MegaTaskInfo[] tasks;
  477. void MakeThreads()
  478. {
  479. if ( Cores > 0 )
  480. {
  481. isRunning = true;
  482. tasks = new MegaTaskInfo[Cores];
  483. for ( int i = 0; i < Cores; i++ )
  484. {
  485. tasks[i] = new MegaTaskInfo();
  486. tasks[i].name = "ThreadID " + i;
  487. tasks[i].pauseevent = new AutoResetEvent(false);
  488. tasks[i]._thread = new Thread(DoWork);
  489. tasks[i]._thread.Start(tasks[i]);
  490. }
  491. }
  492. }
  493. #endif
  494. // Per modifyobject to use mt or not
  495. // auto bias of first task on num of waits
  496. public void ModifyObjectMT()
  497. {
  498. //#if UNITY_4 || UNITY_5 || UNITY_2017 || UNITY_2018 || UNITY_2019
  499. #if UNITY_EDITOR
  500. //if ( !Application.isPlaying && Selection.activeGameObject != gameObject )
  501. //{
  502. //return;
  503. //}
  504. #endif
  505. //#endif
  506. #if UNITY_FLASH || UNITY_PS3 || UNITY_METRO || UNITY_WP8
  507. ModifyObject();
  508. #else
  509. if ( Cores == 0 )
  510. Cores = SystemInfo.processorCount - 1;
  511. // Dont use mt in editor mode
  512. if ( !UseThreading || !ThreadingOn || Cores < 1 || !Application.isPlaying )
  513. {
  514. ModifyObject();
  515. return;
  516. }
  517. if ( tasks == null )
  518. MakeThreads();
  519. if ( Enabled && mods != null )
  520. {
  521. dirtyChannels = MegaModChannel.None;
  522. //if ( GrabVerts )
  523. //{
  524. //if ( sverts.Length < mesh.vertexCount )
  525. //sverts = new Vector3[mesh.vertexCount];
  526. //verts = mesh.vertices;
  527. //}
  528. VertsSource = true;
  529. UVsSource = true;
  530. modContext.mod = this;
  531. PrepareForMT();
  532. // Set up tasks
  533. int step = verts.Length / (Cores + 1);
  534. if ( Cores > 0 )
  535. {
  536. int index = step;
  537. for ( int i = 0; i < tasks.Length; i++ )
  538. {
  539. tasks[i].jobtype = MegaJobType.Modifier;
  540. tasks[i].index = i + 1;
  541. tasks[i].cores = tasks.Length;
  542. tasks[i].start = index;
  543. tasks[i].end = index + step;
  544. tasks[i].modcontext = modContext;
  545. index += step;
  546. }
  547. tasks[Cores - 1].end = verts.Length;
  548. for ( int i = 0; i < tasks.Length; i++ )
  549. tasks[i].pauseevent.Set();
  550. }
  551. // Do this thread work
  552. DoWork1(0, step); // Bias the first job to reduce wait
  553. // Now need to sit and wait for jobs done, we should be doing work here
  554. WaitJobs();
  555. for ( int m = 0; m < mods.Length; m++ )
  556. {
  557. MegaModifier mod = mods[m];
  558. if ( mod.valid )
  559. mod.DoneMT(this);
  560. }
  561. Done();
  562. if ( UpdateMesh == 1 )
  563. {
  564. SetMesh(ref sverts);
  565. UpdateMesh = 0;
  566. }
  567. else
  568. {
  569. if ( UpdateMesh == 0 )
  570. {
  571. SetMesh(ref verts);
  572. UpdateMesh = -1; // Dont need to set verts again until a mod is enabled
  573. }
  574. }
  575. }
  576. #endif
  577. }
  578. void PrepareForMT()
  579. {
  580. selection = null;
  581. for ( int m = 0; m < mods.Length; m++ )
  582. {
  583. MegaModifier mod = mods[m];
  584. mod.valid = false;
  585. if ( mod != null && mod.ModEnabled )
  586. {
  587. modContext.Offset = mod.Offset;
  588. modContext.bbox = mod.bbox;
  589. mod.SetTM();
  590. if ( mod.ModLateUpdate(modContext) )
  591. {
  592. mod.valid = true;
  593. if ( (mod.ChannelsReq() & MegaModChannel.Verts) != 0 )
  594. {
  595. mod.verts = GetSourceVerts(); // is this a ref or does it do a copy
  596. mod.sverts = GetDestVerts();
  597. }
  598. if ( UpdateMesh < 1 )
  599. UpdateMesh = 1;
  600. dirtyChannels |= mod.ChannelsChanged();
  601. }
  602. mod.selection = selection;
  603. mod.PrepareMT(this, Cores + 1);
  604. }
  605. }
  606. }
  607. #if !UNITY_FLASH && !UNITY_PS3 && !UNITY_METRO && !UNITY_WP8
  608. static bool isRunning = true;
  609. // Seperate task info for a morph mod as wont be doing all verts
  610. void DoWork(object info)
  611. {
  612. MegaTaskInfo inf = (MegaTaskInfo)info;
  613. while ( isRunning )
  614. {
  615. inf.pauseevent.WaitOne(Timeout.Infinite, false);
  616. switch ( inf.jobtype )
  617. {
  618. case MegaJobType.Modifier:
  619. if ( inf.end > 0 )
  620. {
  621. for ( int m = 0; m < inf.modcontext.mod.mods.Length; m++ )
  622. {
  623. MegaModifier mod = inf.modcontext.mod.mods[m];
  624. if ( mod.valid )
  625. mod.DoWork(this, inf.index, inf.start, inf.end, Cores + 1);
  626. }
  627. }
  628. break;
  629. case MegaJobType.FaceNormalCalc:
  630. RecalcFaceNormalsMT(inf.modcontext.mod, inf.index, Cores + 1);
  631. break;
  632. case MegaJobType.VertexNormalCalc:
  633. RecalcVertexNormalsMT(inf.modcontext.mod, inf.index, Cores + 1);
  634. break;
  635. case MegaJobType.FaceTangentCalc:
  636. BuildFaceTangentsMT(inf.modcontext.mod, inf.index, Cores + 1);
  637. break;
  638. case MegaJobType.VertexTangentCalc:
  639. BuildVertexTangentsMT(inf.modcontext.mod, inf.index, Cores + 1);
  640. break;
  641. }
  642. inf.end = 0; // Done the job
  643. }
  644. }
  645. #endif
  646. void DoWork1(int start, int end)
  647. {
  648. for ( int m = 0; m < mods.Length; m++ )
  649. {
  650. MegaModifier mod = mods[m];
  651. if ( mod.valid )
  652. {
  653. mod.DoWork(this, 0, start, end, Cores + 1);
  654. }
  655. }
  656. }
  657. void OnApplicationQuit()
  658. {
  659. if ( Application.isPlaying )
  660. {
  661. MegaModifiers[] modsrunning = (MegaModifiers[])Resources.FindObjectsOfTypeAll(typeof(MegaModifiers));
  662. if ( modsrunning.Length == 1 )
  663. {
  664. #if !UNITY_FLASH && !UNITY_PS3 && !UNITY_METRO && !UNITY_WP8
  665. isRunning = false;
  666. if ( tasks != null )
  667. {
  668. for ( int i = 0; i < tasks.Length; i++ )
  669. {
  670. tasks[i].pauseevent.Set();
  671. while ( tasks[i]._thread.IsAlive )
  672. {
  673. }
  674. }
  675. }
  676. tasks = null;
  677. #endif
  678. }
  679. }
  680. }
  681. void Done()
  682. {
  683. for ( int m = 0; m < mods.Length; m++ )
  684. {
  685. MegaModifier mod = mods[m];
  686. if ( mod.valid )
  687. mod.ModEnd(this);
  688. }
  689. }
  690. // New vertex normal calculator
  691. int[] FindFacesUsing(Vector3 p, Vector3 n)
  692. {
  693. List<int> faces = new List<int>();
  694. Vector3 v = Vector3.zero;
  695. for ( int i = 0; i < tris.Length; i += 3 )
  696. {
  697. v = verts[tris[i]];
  698. if ( v.x == p.x && v.y == p.y && v.z == p.z )
  699. {
  700. if ( n.Equals(norms[tris[i]]) )
  701. faces.Add(i / 3);
  702. }
  703. else
  704. {
  705. v = verts[tris[i + 1]];
  706. if ( v.x == p.x && v.y == p.y && v.z == p.z )
  707. {
  708. if ( n.Equals(norms[tris[i + 1]]) )
  709. faces.Add(i / 3);
  710. }
  711. else
  712. {
  713. v = verts[tris[i + 2]];
  714. if ( v.x == p.x && v.y == p.y && v.z == p.z )
  715. {
  716. if ( n.Equals(norms[tris[i + 2]]) )
  717. faces.Add(i / 3);
  718. }
  719. }
  720. }
  721. }
  722. return faces.ToArray();
  723. }
  724. public MegaNormMap[] mapping;
  725. public int[] tris;
  726. public Vector3[] facenorms;
  727. public Vector3[] norms;
  728. // Should call this from inspector when we change to mega
  729. public void BuildNormalMapping(Mesh mesh, bool force)
  730. {
  731. if ( mapping == null || mapping.Length == 0 || force )
  732. {
  733. // so for each normal we have a vertex, so find all faces that share that vertex
  734. tris = mesh.triangles;
  735. norms = mesh.normals;
  736. facenorms = new Vector3[tris.Length / 3];
  737. mapping = new MegaNormMap[verts.Length];
  738. for ( int i = 0; i < verts.Length; i++ )
  739. {
  740. mapping[i] = new MegaNormMap();
  741. mapping[i].faces = FindFacesUsing(verts[i], norms[i]);
  742. }
  743. }
  744. }
  745. // My version of recalc normals
  746. public void RecalcNormals(Mesh ms, Vector3[] _verts)
  747. {
  748. // so first need to recalc face normals
  749. // then we need a map of which faces each normal in the list uses to build its new normal value
  750. // to build new normal its a case of add up face normals used and average, so slow bit will be face norm calc, and preprocess of
  751. // building map of faces used by a normal
  752. int index = 0;
  753. Vector3 v30 = Vector3.zero;
  754. Vector3 v31 = Vector3.zero;
  755. Vector3 v32 = Vector3.zero;
  756. Vector3 va = Vector3.zero;
  757. Vector3 vb = Vector3.zero;
  758. for ( int f = 0; f < tris.Length; f += 3 )
  759. {
  760. v30 = _verts[tris[f]];
  761. v31 = _verts[tris[f + 1]];
  762. v32 = _verts[tris[f + 2]];
  763. va.x = v31.x - v30.x;
  764. va.y = v31.y - v30.y;
  765. va.z = v31.z - v30.z;
  766. vb.x = v32.x - v31.x;
  767. vb.y = v32.y - v31.y;
  768. vb.z = v32.z - v31.z;
  769. v30.x = va.y * vb.z - va.z * vb.y;
  770. v30.y = va.z * vb.x - va.x * vb.z;
  771. v30.z = va.x * vb.y - va.y * vb.x;
  772. // Uncomment this if you dont want normals weighted by poly size
  773. //float l = v30.x * v30.x + v30.y * v30.y + v30.z * v30.z;
  774. //l = 1.0f / Mathf.Sqrt(l);
  775. //v30.x *= l;
  776. //v30.y *= l;
  777. //v30.z *= l;
  778. facenorms[index++] = v30;
  779. }
  780. for ( int n = 0; n < norms.Length; n++ )
  781. {
  782. if ( mapping[n].faces.Length > 0 )
  783. {
  784. Vector3 norm = facenorms[mapping[n].faces[0]];
  785. for ( int i = 1; i < mapping[n].faces.Length; i++ )
  786. {
  787. v30 = facenorms[mapping[n].faces[i]];
  788. norm.x += v30.x;
  789. norm.y += v30.y;
  790. norm.z += v30.z;
  791. }
  792. float l = norm.x * norm.x + norm.y * norm.y + norm.z * norm.z;
  793. l = 1.0f / Mathf.Sqrt(l);
  794. norm.x *= l;
  795. norm.y *= l;
  796. norm.z *= l;
  797. norms[n] = norm;
  798. }
  799. else
  800. norms[n] = Vector3.up;
  801. }
  802. ms.normals = norms;
  803. }
  804. // Threaded normal calculator
  805. public void RecalcFaceNormalsMT(MegaModifiers mod, int cnum, int cores)
  806. {
  807. Vector3 v30 = Vector3.zero;
  808. Vector3 v31 = Vector3.zero;
  809. Vector3 v32 = Vector3.zero;
  810. Vector3 va = Vector3.zero;
  811. Vector3 vb = Vector3.zero;
  812. int step = (mod.tris.Length / 3) / cores;
  813. int start = (cnum * step) * 3;
  814. int end = start + (step * 3);
  815. if ( cnum == cores - 1 )
  816. end = mod.tris.Length;
  817. int index = start / 3;
  818. for ( int f = start; f < end; f += 3 )
  819. {
  820. v30 = mod.sverts[mod.tris[f]];
  821. v31 = mod.sverts[mod.tris[f + 1]];
  822. v32 = mod.sverts[mod.tris[f + 2]];
  823. va.x = v31.x - v30.x;
  824. va.y = v31.y - v30.y;
  825. va.z = v31.z - v30.z;
  826. vb.x = v32.x - v31.x;
  827. vb.y = v32.y - v31.y;
  828. vb.z = v32.z - v31.z;
  829. v30.x = va.y * vb.z - va.z * vb.y;
  830. v30.y = va.z * vb.x - va.x * vb.z;
  831. v30.z = va.x * vb.y - va.y * vb.x;
  832. // Uncomment this if you dont want normals weighted by poly size
  833. //float l = v30.x * v30.x + v30.y * v30.y + v30.z * v30.z;
  834. //l = 1.0f / Mathf.Sqrt(l);
  835. //v30.x *= l;
  836. //v30.y *= l;
  837. //v30.z *= l;
  838. mod.facenorms[index++] = v30;
  839. }
  840. }
  841. public void RecalcVertexNormalsMT(MegaModifiers mod, int cnum, int cores)
  842. {
  843. Vector3 v30 = Vector3.zero;
  844. int step = mod.norms.Length / cores;
  845. int start = cnum * step;
  846. int end = start + step;
  847. if ( cnum == cores - 1 )
  848. end = mod.norms.Length;
  849. for ( int n = start; n < end; n++ )
  850. {
  851. if ( mod.mapping[n].faces.Length > 0 )
  852. {
  853. Vector3 norm = mod.facenorms[mod.mapping[n].faces[0]];
  854. for ( int i = 1; i < mod.mapping[n].faces.Length; i++ )
  855. {
  856. v30 = mod.facenorms[mod.mapping[n].faces[i]];
  857. norm.x += v30.x;
  858. norm.y += v30.y;
  859. norm.z += v30.z;
  860. }
  861. float l = norm.x * norm.x + norm.y * norm.y + norm.z * norm.z;
  862. l = 1.0f / Mathf.Sqrt(l);
  863. norm.x *= l;
  864. norm.y *= l;
  865. norm.z *= l;
  866. mod.norms[n] = norm;
  867. }
  868. else
  869. mod.norms[n] = Vector3.up;
  870. }
  871. }
  872. #if !UNITY_FLASH && !UNITY_PS3 && !UNITY_METRO && !UNITY_WP8
  873. void WaitJobs()
  874. {
  875. if ( Cores > 0 )
  876. {
  877. int count = 0;
  878. bool wait = false;
  879. do
  880. {
  881. wait = false;
  882. for ( int i = 0; i < tasks.Length; i++ )
  883. {
  884. if ( tasks[i].end > 0 )
  885. {
  886. wait = true;
  887. break;
  888. }
  889. }
  890. if ( wait )
  891. {
  892. count++;
  893. Thread.Sleep(0);
  894. }
  895. } while ( wait );
  896. }
  897. }
  898. public void RecalcNormalsMT(Mesh ms, Vector3[] _verts)
  899. {
  900. // so first need to recalc face normals
  901. // then we need a map of which faces each normal in the list uses to build its new normal value
  902. // to build new normal its a case of add up face normals used and average, so slow bit will be face norm calc, and preprocess of
  903. // building map of faces used by a normal
  904. for ( int i = 0; i < Cores; i++ )
  905. {
  906. tasks[i].jobtype = MegaJobType.FaceNormalCalc;
  907. tasks[i].end = 1;
  908. tasks[i].pauseevent.Set();
  909. }
  910. // Do this thread work
  911. RecalcFaceNormalsMT(this, 0, Cores + 1); // Bias the first job to reduce wait
  912. WaitJobs();
  913. for ( int i = 0; i < Cores; i++ )
  914. {
  915. tasks[i].jobtype = MegaJobType.VertexNormalCalc;
  916. tasks[i].end = 1;
  917. tasks[i].pauseevent.Set();
  918. }
  919. RecalcVertexNormalsMT(this, 0, Cores + 1); // Bias the first job to reduce wait
  920. WaitJobs();
  921. ms.normals = norms;
  922. }
  923. void BuildTangentsMT(Mesh ms, Vector3[] _verts)
  924. {
  925. if ( uvs == null )
  926. return;
  927. int vertexCount = _verts.Length;
  928. if ( tan1 == null || tan1.Length != vertexCount )
  929. tan1 = new Vector3[vertexCount];
  930. if ( tan2 == null || tan2.Length != vertexCount )
  931. tan2 = new Vector3[vertexCount];
  932. if ( tangents == null || tangents.Length != vertexCount )
  933. tangents = new Vector4[vertexCount];
  934. if ( tris == null || tris.Length == 0 )
  935. tris = ms.triangles;
  936. if ( norms == null || norms.Length == 0 )
  937. norms = ms.normals;
  938. // Do task set up and start jobs
  939. for ( int i = 0; i < Cores; i++ )
  940. {
  941. tasks[i].jobtype = MegaJobType.FaceTangentCalc;
  942. tasks[i].end = 1;
  943. tasks[i].pauseevent.Set();
  944. }
  945. // Do this thread work
  946. BuildFaceTangentsMT(this, 0, Cores + 1); // Bias the first job to reduce wait
  947. WaitJobs();
  948. for ( int i = 0; i < Cores; i++ )
  949. {
  950. tasks[i].jobtype = MegaJobType.VertexTangentCalc;
  951. tasks[i].end = 1;
  952. tasks[i].pauseevent.Set();
  953. }
  954. BuildVertexTangentsMT(this, 0, Cores + 1); // Bias the first job to reduce wait
  955. WaitJobs();
  956. mesh.tangents = tangents;
  957. }
  958. void BuildFaceTangentsMT(MegaModifiers mc, int cnum, int cores)
  959. {
  960. int triangleCount = mc.tris.Length;
  961. int step = (triangleCount / 3) / cores;
  962. int start = (cnum * step) * 3;
  963. int end = start + (step * 3);
  964. if ( cnum == cores - 1 )
  965. end = triangleCount;
  966. Vector3 v1 = Vector3.zero;
  967. Vector3 v2 = Vector3.zero;
  968. Vector3 v3 = Vector3.zero;
  969. Vector2 w1 = Vector3.zero;
  970. Vector2 w2 = Vector3.zero;
  971. Vector2 w3 = Vector3.zero;
  972. int i1,i2,i3;
  973. for ( int a = start; a < end; a += 3 )
  974. {
  975. i1 = mc.tris[a];
  976. i2 = mc.tris[a + 1];
  977. i3 = mc.tris[a + 2];
  978. v1 = mc.sverts[i1];
  979. v2 = mc.sverts[i2];
  980. v3 = mc.sverts[i3];
  981. w1 = mc.uvs[i1];
  982. w2 = mc.uvs[i2];
  983. w3 = mc.uvs[i3];
  984. float x1 = v2.x - v1.x;
  985. float x2 = v3.x - v1.x;
  986. float y1 = v2.y - v1.y;
  987. float y2 = v3.y - v1.y;
  988. float z1 = v2.z - v1.z;
  989. float z2 = v3.z - v1.z;
  990. float s1 = w2.x - w1.x;
  991. float s2 = w3.x - w1.x;
  992. float t1 = w2.y - w1.y;
  993. float t2 = w3.y - w1.y;
  994. float r = 1.0f / (s1 * t2 - s2 * t1);
  995. Vector3 sdir = new Vector3((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r);
  996. Vector3 tdir = new Vector3((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r);
  997. lock(mc)
  998. {
  999. mc.tan1[i1].x += sdir.x;
  1000. mc.tan1[i1].y += sdir.y;
  1001. mc.tan1[i1].z += sdir.z;
  1002. mc.tan1[i2].x += sdir.x;
  1003. mc.tan1[i2].y += sdir.y;
  1004. mc.tan1[i2].z += sdir.z;
  1005. mc.tan1[i3].x += sdir.x;
  1006. mc.tan1[i3].y += sdir.y;
  1007. mc.tan1[i3].z += sdir.z;
  1008. mc.tan2[i1].x += tdir.x;
  1009. mc.tan2[i1].y += tdir.y;
  1010. mc.tan2[i1].z += tdir.z;
  1011. mc.tan2[i2].x += tdir.x;
  1012. mc.tan2[i2].y += tdir.y;
  1013. mc.tan2[i2].z += tdir.z;
  1014. mc.tan2[i3].x += tdir.x;
  1015. mc.tan2[i3].y += tdir.y;
  1016. mc.tan2[i3].z += tdir.z;
  1017. }
  1018. }
  1019. }
  1020. void BuildVertexTangentsMT(MegaModifiers mc, int cnum, int cores)
  1021. {
  1022. int vertexCount = mc.sverts.Length;
  1023. int step = vertexCount / cores;
  1024. int start = cnum * step;
  1025. int end = start + step;
  1026. if ( cnum == cores - 1 )
  1027. end = vertexCount;
  1028. for ( int a = start; a < end; a++ )
  1029. {
  1030. Vector3 n = mc.norms[a];
  1031. Vector3 t = mc.tan1[a];
  1032. Vector3.OrthoNormalize(ref n, ref t);
  1033. mc.tangents[a].x = t.x;
  1034. mc.tangents[a].y = t.y;
  1035. mc.tangents[a].z = t.z;
  1036. mc.tangents[a].w = (Vector3.Dot(Vector3.Cross(n, t), mc.tan2[a]) < 0.0f) ? -1.0f : 1.0f;
  1037. }
  1038. }
  1039. #endif // UNITYFLASH
  1040. // ***************************************************************************
  1041. // PS3 Code
  1042. // ***************************************************************************
  1043. #if true //UNITY_PS3
  1044. void Awake()
  1045. {
  1046. #if UNITY_5_5 || UNITY_5_6 || UNITY_2017 || UNITY_2018 || UNITY_2019 || UNITY_2020
  1047. #else
  1048. if ( Application.platform == RuntimePlatform.PS3 && !Application.isEditor )
  1049. {
  1050. Mesh ps3mesh = MegaUtils.GetMesh(gameObject);
  1051. BuildPS3Mapping(verts, ps3mesh.vertices);
  1052. }
  1053. #endif
  1054. }
  1055. Vector3[] ps3verts;
  1056. MegaPS3Vert[] ps3mapping;
  1057. // PS3 vertices that use an orginal mesh vertex
  1058. public class MegaPS3Vert
  1059. {
  1060. public int[] indices;
  1061. }
  1062. // List to hold the shared indicies
  1063. static List<int> matches = new List<int>();
  1064. // Build an array of ps3 vertices that match an original vertex
  1065. int[] FindMatches(Vector3 p, Vector3[] array)
  1066. {
  1067. matches.Clear();
  1068. for ( int i = 0; i < array.Length; i++ )
  1069. {
  1070. if ( array[i].x == p.x && array[i].y == p.y && array[i].z == p.z )
  1071. matches.Add(i);
  1072. }
  1073. return matches.ToArray();
  1074. }
  1075. // Build a mapping table for each original mesh vertex to find the vertices that share its position
  1076. public void BuildPS3Mapping(Vector3[] oldverts, Vector3[] newverts)
  1077. {
  1078. ps3verts = new Vector3[newverts.Length];
  1079. ps3mapping = new MegaPS3Vert[oldverts.Length];
  1080. for ( int i = 0; i < oldverts.Length; i++ )
  1081. {
  1082. MegaPS3Vert ps3vert = new MegaPS3Vert();
  1083. ps3vert.indices = FindMatches(oldverts[i], newverts);
  1084. ps3mapping[i] = ps3vert;
  1085. }
  1086. }
  1087. // Set the PS3 mesh vertices from the internal modified vertex array to the new ps3 vertex array
  1088. public void SetPS3Mesh()
  1089. {
  1090. // This is here to test the remapping works in editor mode,
  1091. // remove for use as Awake() will do this.
  1092. if ( ps3mapping == null || ps3mapping.Length == 0 )
  1093. {
  1094. Mesh ps3mesh = MegaUtils.GetMesh(gameObject);
  1095. BuildPS3Mapping(verts, ps3mesh.vertices);
  1096. }
  1097. if ( (dirtyChannels & MegaModChannel.Verts) != 0 )
  1098. {
  1099. for ( int i = 0; i < sverts.Length; i++ )
  1100. {
  1101. for ( int m = 0; m < ps3mapping[i].indices.Length; m++ )
  1102. ps3verts[ps3mapping[i].indices[m]] = sverts[i];
  1103. }
  1104. mesh.vertices = ps3verts;
  1105. }
  1106. if ( (dirtyChannels & MegaModChannel.UV) != 0 )
  1107. mesh.uv = suvs;
  1108. if ( recalcnorms )
  1109. {
  1110. RecalcNormals();
  1111. }
  1112. if ( recalcTangents )
  1113. BuildTangents();
  1114. if ( recalcbounds )
  1115. mesh.RecalculateBounds();
  1116. if ( recalcCollider )
  1117. {
  1118. if ( meshCol == null )
  1119. meshCol = GetComponent<MeshCollider>();
  1120. if ( meshCol != null )
  1121. {
  1122. meshCol.sharedMesh = null;
  1123. meshCol.sharedMesh = mesh;
  1124. }
  1125. }
  1126. }
  1127. #endif
  1128. }
  1129. // 1553
  1130. // 1326