MegaCacheImage.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
  1. using UnityEngine;
  2. using System.Collections.Generic;
  3. using System;
  4. #if !UNITY_FLASH && !UNITY_PS3 && !UNITY_METRO && !UNITY_WP8
  5. using System.Threading;
  6. #endif
  7. [System.Serializable]
  8. public class MegaCacheImageFrame
  9. {
  10. public int vc;
  11. public int nc;
  12. public int tc;
  13. public int uvc;
  14. public Vector3 bmin;
  15. public Vector3 uvmin;
  16. public Vector3 bsize;
  17. public Vector3 uvsize;
  18. public byte[] verts;
  19. public byte[] norms;
  20. public byte[] tangents;
  21. public byte[] uvs;
  22. public byte[] tris;
  23. public int subcount;
  24. public int[] suboffs;
  25. public int[] sublen;
  26. public MegaCacheImageFace[] subs;
  27. public void LoadSection(MegaCacheOBJ cache)
  28. {
  29. float oo127 = 1.0f / 127.0f;
  30. for ( int i = 0; i < vc; i++ )
  31. {
  32. int ix = i * 6;
  33. cache.vertcache[i].x = bmin.x + ((float)System.BitConverter.ToUInt16(verts, ix) * bsize.x);
  34. cache.vertcache[i].y = bmin.y + ((float)System.BitConverter.ToUInt16(verts, ix + 2) * bsize.y);
  35. cache.vertcache[i].z = bmin.z + ((float)System.BitConverter.ToUInt16(verts, ix + 4) * bsize.z);
  36. }
  37. for ( int i = 0; i < nc; i++ )
  38. {
  39. int ix = i * 3;
  40. cache.normcache[i].x = ((float)norms[ix] - 127.0f) * oo127;
  41. cache.normcache[i].y = ((float)norms[ix + 1] - 127.0f) * oo127;
  42. cache.normcache[i].z = ((float)norms[ix + 2] - 127.0f) * oo127;
  43. }
  44. for ( int i = 0; i < tc; i++ )
  45. {
  46. int ix = i * 4;
  47. cache.tangentcache[i].x = ((float)tangents[ix] - 127.0f) * oo127;
  48. cache.tangentcache[i].y = ((float)tangents[ix + 1] - 127.0f) * oo127;
  49. cache.tangentcache[i].z = ((float)tangents[ix + 2] - 127.0f) * oo127;
  50. cache.tangentcache[i].w = ((float)tangents[ix + 3] - 127.0f) * oo127;
  51. }
  52. for ( int i = 0; i < uvc; i++ )
  53. {
  54. int ix = i * 2;
  55. cache.uvcache[i].x = uvmin.x + ((float)uvs[ix] * uvsize.x);
  56. cache.uvcache[i].y = uvmin.y + ((float)uvs[ix + 1] * uvsize.y);
  57. }
  58. for ( int s = 0; s < subcount; s++ )
  59. {
  60. int soff = suboffs[s];
  61. for ( int f = 0; f < sublen[s]; f++ )
  62. cache.subs[s].tris[f] = (int)System.BitConverter.ToUInt16(tris, soff + (f * 2));
  63. for ( int ii = sublen[s]; ii < cache.subs[s].max; ii++ )
  64. cache.subs[s].tris[ii] = cache.subs[s].tris[sublen[s]];
  65. }
  66. }
  67. public void SetMesh(Mesh mesh, MegaCacheOBJ cache)
  68. {
  69. mesh.subMeshCount = subcount;
  70. mesh.vertices = cache.vertcache;
  71. if ( nc > 0 )
  72. mesh.normals = cache.normcache;
  73. if ( uvc > 0 )
  74. mesh.uv = cache.uvcache;
  75. if ( tc > 0 )
  76. mesh.tangents = cache.tangentcache;
  77. for ( int s = 0; s < subcount; s++ )
  78. mesh.SetTriangles(cache.subs[s].tris, s);
  79. mesh.RecalculateBounds();
  80. }
  81. public void GetMesh(Mesh mesh, MegaCacheOBJ cache)
  82. {
  83. float oo127 = 1.0f / 127.0f;
  84. cache.framevertcount = vc;
  85. for ( int i = 0; i < vc; i++ )
  86. {
  87. int ix = i * 6;
  88. cache.vertcache[i].x = bmin.x + ((float)System.BitConverter.ToUInt16(verts, ix) * bsize.x);
  89. cache.vertcache[i].y = bmin.y + ((float)System.BitConverter.ToUInt16(verts, ix + 2) * bsize.y);
  90. cache.vertcache[i].z = bmin.z + ((float)System.BitConverter.ToUInt16(verts, ix + 4) * bsize.z);
  91. }
  92. for ( int i = 0; i < nc; i++ )
  93. {
  94. int ix = i * 3;
  95. cache.normcache[i].x = ((float)norms[ix] - 127.0f) * oo127;
  96. cache.normcache[i].y = ((float)norms[ix + 1] - 127.0f) * oo127;
  97. cache.normcache[i].z = ((float)norms[ix + 2] - 127.0f) * oo127;
  98. }
  99. for ( int i = 0; i < tc; i++ )
  100. {
  101. int ix = i * 4;
  102. cache.tangentcache[i].x = ((float)tangents[ix] - 127.0f) * oo127;
  103. cache.tangentcache[i].y = ((float)tangents[ix + 1] - 127.0f) * oo127;
  104. cache.tangentcache[i].z = ((float)tangents[ix + 2] - 127.0f) * oo127;
  105. cache.tangentcache[i].w = ((float)tangents[ix + 3] - 127.0f) * oo127;
  106. }
  107. for ( int i = 0; i < uvc; i++ )
  108. {
  109. int ix = i * 2;
  110. cache.uvcache[i].x = uvmin.x + ((float)uvs[ix] * uvsize.x);
  111. cache.uvcache[i].y = uvmin.y + ((float)uvs[ix + 1] * uvsize.y);
  112. }
  113. mesh.subMeshCount = subcount;
  114. mesh.vertices = cache.vertcache;
  115. if ( nc > 0 )
  116. mesh.normals = cache.normcache;
  117. if ( uvc > 0 )
  118. mesh.uv = cache.uvcache;
  119. if ( tc > 0 )
  120. mesh.tangents = cache.tangentcache;
  121. for ( int s = 0; s < subcount; s++ )
  122. {
  123. int soff = suboffs[s];
  124. for ( int f = 0; f < sublen[s]; f++ )
  125. cache.subs[s].tris[f] = (int)System.BitConverter.ToUInt16(tris, soff + (f * 2));
  126. for ( int ii = sublen[s]; ii < cache.subs[s].max; ii++ )
  127. cache.subs[s].tris[ii] = cache.subs[s].tris[sublen[s]];
  128. }
  129. for ( int s = 0; s < subcount; s++ )
  130. mesh.SetTriangles(cache.subs[s].tris, s);
  131. mesh.RecalculateBounds();
  132. }
  133. }
  134. [System.Serializable]
  135. public class MegaCacheImage : ScriptableObject
  136. {
  137. public List<MegaCacheImageFrame> frames = new List<MegaCacheImageFrame>();
  138. public int maxsm;
  139. public int maxv;
  140. public int maxtris;
  141. public int[] smfc;
  142. public int lastframe = -1;
  143. public int preloaded = -1;
  144. public int memoryuse = 0;
  145. #if !UNITY_FLASH && !UNITY_PS3 && !UNITY_METRO && !UNITY_WP8
  146. public bool threadupdate = false;
  147. public class MegaCacheOBJTaskInfo
  148. {
  149. public string name;
  150. public AutoResetEvent pauseevent;
  151. public Thread _thread;
  152. public MegaCacheOBJ objcache;
  153. public int end;
  154. public int frame;
  155. }
  156. public int Cores = 1;
  157. static bool isRunning = false;
  158. MegaCacheOBJTaskInfo[] tasks;
  159. void MakeThreads(MegaCacheOBJ cache)
  160. {
  161. if ( Cores > 0 )
  162. {
  163. isRunning = true;
  164. tasks = new MegaCacheOBJTaskInfo[Cores];
  165. for ( int i = 0; i < Cores; i++ )
  166. {
  167. tasks[i] = new MegaCacheOBJTaskInfo();
  168. tasks[i].objcache = cache;
  169. tasks[i].name = "ThreadID " + i;
  170. tasks[i].pauseevent = new AutoResetEvent(false);
  171. tasks[i]._thread = new Thread(DoWork);
  172. tasks[i]._thread.Start(tasks[i]);
  173. }
  174. }
  175. }
  176. void DoWork(object info)
  177. {
  178. MegaCacheOBJTaskInfo inf = (MegaCacheOBJTaskInfo)info;
  179. while ( isRunning )
  180. {
  181. inf.pauseevent.WaitOne(Timeout.Infinite, false);
  182. if ( inf.end > 0 )
  183. PreLoad(inf.frame, inf.objcache);
  184. inf.end = 0; // Done the job
  185. }
  186. }
  187. public void GetNextFrame(MegaCacheOBJ cache, int frame)
  188. {
  189. if ( Cores == 0 )
  190. Cores = SystemInfo.processorCount - 1;
  191. if ( Cores < 1 || !Application.isPlaying )
  192. return;
  193. if ( tasks == null )
  194. MakeThreads(cache);
  195. if ( Cores > 0 )
  196. {
  197. for ( int i = 0; i < tasks.Length; i++ )
  198. {
  199. tasks[i].objcache = cache;
  200. tasks[i].end = 1;
  201. tasks[i].frame = frame;
  202. }
  203. for ( int i = 0; i < tasks.Length; i++ )
  204. tasks[i].pauseevent.Set();
  205. }
  206. }
  207. void OnDestroy()
  208. {
  209. if ( Application.isPlaying )
  210. {
  211. isRunning = false;
  212. if ( tasks != null )
  213. {
  214. for ( int i = 0; i < tasks.Length; i++ )
  215. {
  216. tasks[i].pauseevent.Set();
  217. while ( tasks[i]._thread.IsAlive )
  218. {
  219. }
  220. }
  221. }
  222. tasks = null;
  223. }
  224. }
  225. #else
  226. public void GetNextFrame(MegaCacheOBJ cache, int frame)
  227. {
  228. PreLoad(frame, cache);
  229. }
  230. #endif
  231. public void PreLoad(int frame, MegaCacheOBJ cache)
  232. {
  233. if ( frame != preloaded )
  234. {
  235. preloaded = frame;
  236. frames[frame].LoadSection(cache);
  237. }
  238. }
  239. public void GetMesh(Mesh mesh, int frame, MegaCacheOBJ cache)
  240. {
  241. #if !UNITY_FLASH && !UNITY_PS3 && !UNITY_METRO && !UNITY_WP8
  242. if ( threadupdate && Application.isPlaying )
  243. GetMeshPreLoaded(mesh, frame, cache);
  244. else
  245. {
  246. if ( frame != lastframe )
  247. {
  248. lastframe = frame;
  249. frames[frame].GetMesh(mesh, cache);
  250. }
  251. }
  252. #else
  253. if ( frame != lastframe )
  254. {
  255. lastframe = frame;
  256. frames[frame].GetMesh(mesh, cache);
  257. }
  258. #endif
  259. }
  260. public void GetMeshRef(Mesh mesh, int frame, MegaCacheOBJ cache)
  261. {
  262. frames[frame].GetMesh(mesh, cache);
  263. }
  264. public void GetMeshPreLoaded(Mesh mesh, int frame, MegaCacheOBJ cache)
  265. {
  266. if ( frame != lastframe )
  267. {
  268. if ( frame == preloaded )
  269. frames[frame].SetMesh(mesh, cache);
  270. else
  271. frames[frame].GetMesh(mesh, cache);
  272. int next = frame + 1;
  273. if ( next >= frames.Count )
  274. next = 0;
  275. GetNextFrame(cache, next);
  276. lastframe = frame;
  277. }
  278. }
  279. public int CalcMemory()
  280. {
  281. int mem = 0;
  282. for ( int i = 0; i < frames.Count; i++ )
  283. {
  284. MegaCacheImageFrame fr = frames[i];
  285. mem += fr.verts.Length;
  286. mem += fr.norms.Length;
  287. mem += fr.tangents.Length;
  288. mem += fr.uvs.Length;
  289. mem += fr.tris.Length;
  290. mem += fr.suboffs.Length * 2;
  291. mem += fr.sublen.Length * 2;
  292. }
  293. memoryuse = mem;
  294. return mem;
  295. }
  296. static public MegaCacheImageFrame CreateImageFrame(Mesh ms)
  297. {
  298. MegaCacheImageFrame frame = new MegaCacheImageFrame();
  299. Vector3[] verts = ms.vertices;
  300. Vector3[] norms = ms.normals;
  301. Vector2[] uvs = ms.uv;
  302. Vector4[] tangents = ms.tangents;
  303. frame.vc = verts.Length;
  304. frame.nc = norms.Length;
  305. frame.tc = tangents.Length;
  306. frame.uvc = uvs.Length;
  307. frame.bmin = ms.bounds.min;
  308. //Vector3 bmax = ms.bounds.max;
  309. Vector3 msize = ms.bounds.size;
  310. frame.bsize = ms.bounds.size * (1.0f / 65535.0f);
  311. Bounds uvb = MegaCacheUtils.GetBounds(uvs);
  312. frame.uvmin = uvb.min;
  313. frame.uvsize = uvb.size * (1.0f / 255.0f);
  314. frame.verts = new byte[frame.vc * 6];
  315. frame.norms = new byte[frame.nc * 3];
  316. frame.tangents = new byte[frame.tc * 4];
  317. frame.uvs = new byte[frame.vc * 2];
  318. frame.tris = new byte[ms.triangles.Length * 2];
  319. int ix = 0;
  320. byte[] by;
  321. for ( int v = 0; v < verts.Length; v++ )
  322. {
  323. Vector3 pos = verts[v];
  324. short val = (short)(((pos.x - frame.bmin.x) / msize.x) * 65535.0f);
  325. by = System.BitConverter.GetBytes(val);
  326. frame.verts[ix++] = by[0];
  327. frame.verts[ix++] = by[1];
  328. val = (short)(((pos.y - frame.bmin.y) / msize.y) * 65535.0f);
  329. by = System.BitConverter.GetBytes(val);
  330. frame.verts[ix++] = by[0];
  331. frame.verts[ix++] = by[1];
  332. val = (short)(((pos.z - frame.bmin.z) / msize.z) * 65535.0f);
  333. by = System.BitConverter.GetBytes(val);
  334. frame.verts[ix++] = by[0];
  335. frame.verts[ix++] = by[1];
  336. }
  337. ix = 0;
  338. for ( int v = 0; v < norms.Length; v++ )
  339. {
  340. Vector3 pos = norms[v];
  341. frame.norms[ix++] = (byte)((pos.x + 1.0f) * 127.0f);
  342. frame.norms[ix++] = (byte)((pos.y + 1.0f) * 127.0f);
  343. frame.norms[ix++] = (byte)((pos.z + 1.0f) * 127.0f);
  344. }
  345. ix = 0;
  346. for ( int v = 0; v < tangents.Length; v++ )
  347. {
  348. Vector4 pos = tangents[v];
  349. frame.tangents[ix++] = (byte)((pos.x + 1.0f) * 127.0f);
  350. frame.tangents[ix++] = (byte)((pos.y + 1.0f) * 127.0f);
  351. frame.tangents[ix++] = (byte)((pos.z + 1.0f) * 127.0f);
  352. frame.tangents[ix++] = (byte)((pos.w + 1.0f) * 127.0f);
  353. }
  354. ix = 0;
  355. for ( int v = 0; v < uvs.Length; v++ )
  356. {
  357. Vector2 pos = uvs[v];
  358. frame.uvs[ix++] = (byte)(((pos.x - uvb.min.x) / uvb.size.x) * 255.0f);
  359. frame.uvs[ix++] = (byte)(((pos.y - uvb.min.y) / uvb.size.y) * 255.0f);
  360. }
  361. frame.subcount = ms.subMeshCount;
  362. frame.suboffs = new int[frame.subcount];
  363. frame.sublen = new int[frame.subcount];
  364. ix = 0;
  365. for ( int s = 0; s < frame.subcount; s++ )
  366. {
  367. int[] tris = ms.GetTriangles(s);
  368. frame.suboffs[s] = ix;
  369. frame.sublen[s] = tris.Length;
  370. for ( int t = 0; t < tris.Length; t++ )
  371. {
  372. short val = (short)tris[t];
  373. by = System.BitConverter.GetBytes(val);
  374. frame.tris[ix++] = by[0];
  375. frame.tris[ix++] = by[1];
  376. }
  377. }
  378. return frame;
  379. }
  380. }