MegaCacheOBJEditor.cs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761
  1. using UnityEngine;
  2. using UnityEditor;
  3. using System;
  4. using System.IO;
  5. [CustomEditor(typeof(MegaCacheOBJ))]
  6. public class MegaCacheOBJEditor : Editor
  7. {
  8. SerializedProperty _prop_firstframe;
  9. SerializedProperty _prop_lastframe;
  10. SerializedProperty _prop_skip;
  11. SerializedProperty _prop_scale;
  12. SerializedProperty _prop_adjustcords;
  13. SerializedProperty _prop_buildtangents;
  14. SerializedProperty _prop_loadmtls;
  15. SerializedProperty _prop_saveuvs;
  16. SerializedProperty _prop_savenormals;
  17. SerializedProperty _prop_savetangents;
  18. SerializedProperty _prop_optimize;
  19. SerializedProperty _prop_time;
  20. SerializedProperty _prop_fps;
  21. SerializedProperty _prop_speed;
  22. SerializedProperty _prop_loopmode;
  23. SerializedProperty _prop_frame;
  24. SerializedProperty _prop_runtimefolder;
  25. SerializedProperty _prop_updatecollider;
  26. SerializedProperty _prop_recalcnormals;
  27. [MenuItem("GameObject/Create Other/MegaCache/OBJ Cache")]
  28. static void CreateOBJCache()
  29. {
  30. Vector3 pos = Vector3.zero;
  31. if ( UnityEditor.SceneView.lastActiveSceneView != null )
  32. pos = UnityEditor.SceneView.lastActiveSceneView.pivot;
  33. GameObject go = new GameObject("Mega Cache Obj");
  34. go.AddComponent<MegaCacheOBJ>();
  35. go.transform.position = pos;
  36. Selection.activeObject = go;
  37. }
  38. private void OnEnable()
  39. {
  40. _prop_firstframe = serializedObject.FindProperty("firstframe");
  41. _prop_lastframe = serializedObject.FindProperty("lastframe");
  42. _prop_skip = serializedObject.FindProperty("skip");
  43. _prop_scale = serializedObject.FindProperty("scale");
  44. _prop_adjustcords = serializedObject.FindProperty("adjustcoord");
  45. _prop_buildtangents = serializedObject.FindProperty("buildtangents");
  46. _prop_loadmtls = serializedObject.FindProperty("loadmtls");
  47. _prop_saveuvs = serializedObject.FindProperty("saveuvs");
  48. _prop_savenormals = serializedObject.FindProperty("savenormals");
  49. _prop_savetangents = serializedObject.FindProperty("savetangents");
  50. _prop_optimize = serializedObject.FindProperty("optimize");
  51. _prop_recalcnormals = serializedObject.FindProperty("recalcnormals");
  52. _prop_time = serializedObject.FindProperty("time");
  53. _prop_fps = serializedObject.FindProperty("fps");
  54. _prop_speed = serializedObject.FindProperty("speed");
  55. _prop_loopmode = serializedObject.FindProperty("loopmode");
  56. _prop_frame = serializedObject.FindProperty("frame");
  57. _prop_runtimefolder = serializedObject.FindProperty("runtimefolder");
  58. _prop_updatecollider = serializedObject.FindProperty("updatecollider");
  59. }
  60. public override void OnInspectorGUI()
  61. {
  62. bool undo = true;
  63. MegaCacheOBJ mod = (MegaCacheOBJ)target;
  64. serializedObject.Update();
  65. #if !UNITY_5 && !UNITY_2017 && !UNITY_2018 && !UNITY_2019 && !UNITY_2020
  66. EditorGUIUtility.LookLikeControls();
  67. #endif
  68. EditorGUILayout.BeginVertical("box");
  69. mod.showdataimport = EditorGUILayout.Foldout(mod.showdataimport, "Data Import");
  70. if ( mod.showdataimport )
  71. {
  72. EditorGUILayout.PropertyField(_prop_firstframe, new GUIContent("First"));
  73. EditorGUILayout.PropertyField(_prop_lastframe, new GUIContent("Last"));
  74. EditorGUILayout.PropertyField(_prop_skip, new GUIContent("Skip"));
  75. //int val = 0;
  76. //mod.decformat = EditorGUILayout.IntSlider("Format name" + mod.namesplit + val.ToString("D" + mod.decformat) + ".obj", mod.decformat, 1, 6);
  77. //mod.namesplit = EditorGUILayout.TextField("Name Split Char", mod.namesplit);
  78. EditorGUILayout.PropertyField(_prop_scale, new GUIContent("Import Scale"));
  79. EditorGUILayout.PropertyField(_prop_adjustcords, new GUIContent("Adjust Coords"));
  80. EditorGUILayout.PropertyField(_prop_buildtangents, new GUIContent("Build Tangents"));
  81. EditorGUILayout.PropertyField(_prop_updatecollider, new GUIContent("Update Collider"));
  82. EditorGUILayout.PropertyField(_prop_loadmtls, new GUIContent("Load Materials"));
  83. EditorGUILayout.PropertyField(_prop_recalcnormals, new GUIContent("Recalculate Normals"));
  84. if ( GUILayout.Button("Load Frames") )
  85. {
  86. string file = EditorUtility.OpenFilePanel("OBJ File", mod.lastpath, "obj");
  87. if ( file != null && file.Length > 1 )
  88. {
  89. mod.lastpath = file;
  90. LoadOBJ(mod, file, mod.firstframe, mod.lastframe, mod.skip);
  91. }
  92. }
  93. if ( mod.meshes.Count > 0 )
  94. {
  95. if ( GUILayout.Button("Clear Stored Meshes") )
  96. mod.DestroyMeshes();
  97. }
  98. }
  99. EditorGUILayout.EndVertical();
  100. mod.showdata = EditorGUILayout.Foldout(mod.showdata, "Data");
  101. if ( mod.showdata )
  102. {
  103. MegaCacheData src = (MegaCacheData)EditorGUILayout.EnumPopup("Data Source", mod.datasource);
  104. if ( src != mod.datasource )
  105. mod.ChangeSource(src);
  106. switch ( mod.datasource )
  107. {
  108. case MegaCacheData.Mesh:
  109. if ( mod.meshes.Count > 0 )
  110. {
  111. EditorGUILayout.BeginVertical("box");
  112. EditorGUILayout.PropertyField(_prop_saveuvs, new GUIContent("Save Uvs"));
  113. EditorGUILayout.PropertyField(_prop_savenormals, new GUIContent("Save Normals"));
  114. EditorGUILayout.PropertyField(_prop_savetangents, new GUIContent("Save Tangents"));
  115. EditorGUILayout.PropertyField(_prop_optimize, new GUIContent("Optimize Data"));
  116. if ( GUILayout.Button("Save MegaCache File") )
  117. {
  118. string file = EditorUtility.SaveFilePanel("MegaCache File", mod.lastpath, mod.name, "mgc");
  119. if ( file != null && file.Length > 1 )
  120. {
  121. mod.CloseCache();
  122. CreateCacheFile(file);
  123. if ( mod.cachefile.Length == 0 )
  124. mod.cachefile = file;
  125. }
  126. }
  127. if ( GUILayout.Button("Create Image") )
  128. CreateCacheImage();
  129. EditorGUILayout.EndVertical();
  130. }
  131. break;
  132. case MegaCacheData.File:
  133. EditorGUILayout.BeginVertical("box");
  134. EditorGUILayout.TextArea("Cache File: " + mod.cachefile);
  135. if ( GUILayout.Button("Select MegaCache File") )
  136. {
  137. string file = EditorUtility.OpenFilePanel("MegaCache File", mod.lastpath, "mgc");
  138. if ( file != null && file.Length > 1 )
  139. {
  140. mod.CloseCache();
  141. mod.cachefile = file;
  142. mod.update = true;
  143. mod.OpenCache(mod.cachefile);
  144. }
  145. }
  146. EditorGUILayout.PropertyField(_prop_runtimefolder, new GUIContent("Runtime Folder"));
  147. if ( mod.cachefile.Length > 0 )
  148. {
  149. if ( GUILayout.Button("Create Image From Cache") )
  150. {
  151. bool doit = true;
  152. if ( mod.cacheimage )
  153. {
  154. if ( !EditorUtility.DisplayDialog("Add to or Replace", "Image already loaded do you want to Replace?", "Yes", "No") )
  155. doit = false;
  156. }
  157. if ( doit )
  158. {
  159. mod.CreateImageFromCacheFile();
  160. }
  161. }
  162. }
  163. EditorGUILayout.EndVertical();
  164. break;
  165. case MegaCacheData.Image:
  166. if ( mod.cacheimage )
  167. {
  168. EditorGUILayout.BeginVertical("box");
  169. #if !UNITY_FLASH && !UNITY_PS3 && !UNITY_METRO && !UNITY_WP8
  170. mod.cacheimage.threadupdate = EditorGUILayout.Toggle("Preload", mod.cacheimage.threadupdate);
  171. #endif
  172. if ( GUILayout.Button("Delete Image") )
  173. {
  174. mod.DestroyImage(); // = null;
  175. }
  176. EditorGUILayout.EndVertical();
  177. }
  178. break;
  179. }
  180. string info = "";
  181. info += "Frame Verts: " + mod.framevertcount + "\nFrame Tris: " + (mod.frametricount / 3);
  182. if ( mod.datasource == MegaCacheData.Image )
  183. {
  184. if ( mod.cacheimage )
  185. info += "\nMemory: " + mod.cacheimage.memoryuse / (1024 * 1024) + "MB";
  186. else
  187. info += "\nNo Image File";
  188. }
  189. EditorGUILayout.HelpBox(info, MessageType.None);
  190. }
  191. mod.showanimation = EditorGUILayout.Foldout(mod.showanimation, "Animation");
  192. if ( mod.showanimation )
  193. {
  194. EditorGUILayout.BeginVertical("box");
  195. int fc = 0;
  196. switch ( mod.datasource )
  197. {
  198. case MegaCacheData.Mesh: fc = mod.meshes.Count - 1; break;
  199. case MegaCacheData.File: fc = mod.framecount - 1; break;
  200. case MegaCacheData.Image:
  201. if ( mod.cacheimage && mod.cacheimage.frames != null )
  202. fc = mod.cacheimage.frames.Count - 1;
  203. break;
  204. }
  205. if ( fc > 0 )
  206. EditorGUILayout.IntSlider(_prop_frame, 0, fc);
  207. mod.animate = EditorGUILayout.BeginToggleGroup("Animate", mod.animate);
  208. bool timechange = GUI.changed;
  209. EditorGUILayout.PropertyField(_prop_time, new GUIContent("Time"));
  210. if ( GUI.changed && !timechange )
  211. {
  212. undo = false;
  213. }
  214. EditorGUILayout.PropertyField(_prop_fps, new GUIContent("Fps"));
  215. EditorGUILayout.PropertyField(_prop_speed, new GUIContent("Speed"));
  216. EditorGUILayout.PropertyField(_prop_loopmode, new GUIContent("Loop Mode"));
  217. EditorGUILayout.EndToggleGroup();
  218. EditorGUILayout.EndVertical();
  219. }
  220. mod.showextras = EditorGUILayout.Foldout(mod.showextras, "Extra Options");
  221. if ( mod.showextras )
  222. {
  223. mod.shownormals = EditorGUILayout.BeginToggleGroup("Show Normals", mod.shownormals);
  224. mod.normallen = EditorGUILayout.FloatField("Normal Length", mod.normallen);
  225. EditorGUILayout.EndToggleGroup();
  226. }
  227. if ( GUI.changed )
  228. {
  229. if ( undo )
  230. serializedObject.ApplyModifiedProperties();
  231. else
  232. {
  233. #if UNITY_5_3_OR_NEWER || UNITY_2017 || UNITY_2018 || UNITY_2019 || UNITY_2020
  234. serializedObject.ApplyModifiedPropertiesWithoutUndo();
  235. #else
  236. serializedObject.ApplyModifiedProperties();
  237. #endif
  238. }
  239. EditorUtility.SetDirty(target);
  240. }
  241. }
  242. Material CreateMaterial(string name, string shader)
  243. {
  244. if ( HaveMaterial(name) )
  245. return (Material)AssetDatabase.LoadAssetAtPath("Assets/MegaCache/" + name + ".mat", typeof(Material));
  246. #if UNITY_5_3 || UNITY_5_4 || UNITY_5_5 || UNITY_5_6 || UNITY_2017 || UNITY_2018 || UNITY_2019 || UNITY_2020
  247. Material mat = new Material(Shader.Find("Standard"));
  248. #else
  249. Material mat = new Material(Shader.Find(shader));
  250. #endif
  251. if ( !Directory.Exists("Assets/MegaCache") )
  252. AssetDatabase.CreateFolder("Assets", "MegaCache");
  253. string meshpath = "Assets/MegaCache/" + name + ".mat";
  254. AssetDatabase.CreateAsset(mat, meshpath);
  255. AssetDatabase.SaveAssets();
  256. AssetDatabase.Refresh();
  257. return mat;
  258. }
  259. public void LoadOBJ(MegaCacheOBJ mod, string filename, int first, int last, int step)
  260. {
  261. if ( mod.meshes.Count > 0 )
  262. {
  263. if ( !EditorUtility.DisplayDialog("Add to or Replace", "Add new OBJ meshes to existing list, or Replace All", "Add", "Replace") )
  264. mod.DestroyMeshes();
  265. }
  266. if ( step < 1 )
  267. step = 1;
  268. mod.InitImport();
  269. for ( int i = first; i <= last; i += step )
  270. mod.LoadMtl(filename, i);
  271. for ( int i = first; i <= last; i += step )
  272. {
  273. float a = (float)(i + 1 - first) / (last - first);
  274. if ( !EditorUtility.DisplayCancelableProgressBar("Loading OBJ Meshes", "Frame " + i, a) )
  275. {
  276. Mesh ms = mod.LoadFrame(filename, i);
  277. if ( ms )
  278. mod.AddMesh(ms);
  279. else
  280. {
  281. EditorUtility.DisplayDialog("Can't Load File", "Could not load frame " + i + " of sequence! Import Stopped.", "OK");
  282. break;
  283. }
  284. }
  285. else
  286. break;
  287. }
  288. EditorUtility.ClearProgressBar();
  289. if ( mod.loadmtls )
  290. {
  291. int count = MegaCacheObjImporter.NumMtls();
  292. Material[] mats = new Material[count];
  293. for ( int i = 0; i < count; i++ )
  294. {
  295. MegaCacheOBJMtl mtl = MegaCacheObjImporter.GetMtl(i);
  296. switch ( mtl.illum )
  297. {
  298. case 0:
  299. case 1:
  300. mats[i] = CreateMaterial(mtl.name, "Diffuse");
  301. break;
  302. case 2:
  303. mats[i] = CreateMaterial(mtl.name, "Specular");
  304. #if UNITY_5_3 || UNITY_5_4 || UNITY_5_5 || UNITY_5_6 || UNITY_2017 || UNITY_2018 || UNITY_2019 || UNITY_2020
  305. mats[i].SetColor("_SpecColor", mtl.Ks);
  306. #else
  307. mats[i].SetColor("_SpecCol", mtl.Ks);
  308. #endif
  309. mats[i].SetFloat("_Shininess", mtl.Ns);
  310. break;
  311. case 4:
  312. case 6:
  313. case 7:
  314. case 9:
  315. mats[i] = CreateMaterial(mtl.name, "Transparent/Specular");
  316. #if UNITY_5_3 || UNITY_5_4 || UNITY_5_5 || UNITY_5_6 || UNITY_2017 || UNITY_2018 || UNITY_2019 || UNITY_2020
  317. mats[i].SetColor("_SpecColor", mtl.Ks);
  318. #else
  319. mats[i].SetColor("_SpecCol", mtl.Ks);
  320. #endif
  321. mats[i].SetFloat("_Shininess", mtl.Ns);
  322. break;
  323. case 3:
  324. case 5:
  325. case 8:
  326. mats[i] = CreateMaterial(mtl.name, "Reflection/Specular");
  327. #if UNITY_5_3 || UNITY_5_4 || UNITY_5_5 || UNITY_5_6 || UNITY_2017 || UNITY_2018 || UNITY_2019 || UNITY_2020
  328. mats[i].SetColor("_SpecColor", mtl.Ks);
  329. #else
  330. mats[i].SetColor("_SpecCol", mtl.Ks);
  331. #endif
  332. mats[i].SetFloat("_Shininess", mtl.Ns);
  333. break;
  334. }
  335. mats[i].name = mtl.name;
  336. mats[i].color = mtl.Kd;
  337. if ( mtl.map_Kd != null )
  338. mats[i].mainTexture = LoadTexture(mtl.map_Kd);
  339. AssetDatabase.SaveAssets();
  340. AssetDatabase.Refresh();
  341. }
  342. mod.GetComponent<Renderer>().sharedMaterials = mats;
  343. }
  344. }
  345. void CreateCacheImage()
  346. {
  347. MegaCacheOBJ mod = (MegaCacheOBJ)target;
  348. if ( mod.cacheimage )
  349. mod.DestroyImage();
  350. MegaCacheImage img = CreateInstance<MegaCacheImage>();
  351. img.maxv = 0;
  352. img.maxsm = 0;
  353. for ( int i = 0; i < mod.meshes.Count; i++ )
  354. {
  355. if ( mod.meshes[i].vertexCount > img.maxv )
  356. img.maxv = mod.meshes[i].vertexCount;
  357. int sub = mod.meshes[i].subMeshCount;
  358. if ( sub > img.maxsm )
  359. img.maxsm = sub;
  360. }
  361. img.smfc = new int[img.maxsm];
  362. for ( int i = 0; i < mod.meshes.Count; i++ )
  363. {
  364. for ( int s = 0; s < mod.meshes[i].subMeshCount; s++ )
  365. {
  366. int len = mod.meshes[i].GetTriangles(s).Length;
  367. if ( len > img.smfc[s] )
  368. img.smfc[s] = len;
  369. }
  370. }
  371. for ( int i = 0; i < mod.meshes.Count; i++ )
  372. {
  373. Mesh ms = mod.meshes[i];
  374. MegaCacheImageFrame frame = MegaCacheImage.CreateImageFrame(ms);
  375. img.frames.Add(frame);
  376. }
  377. img.CalcMemory();
  378. mod.cacheimage = img;
  379. }
  380. void CreateCacheFile(string filename)
  381. {
  382. MegaCacheOBJ mod = (MegaCacheOBJ)target;
  383. // save cache file
  384. FileStream fs = new FileStream(filename, FileMode.Create);
  385. if ( fs != null )
  386. {
  387. BinaryWriter bw = new BinaryWriter(fs);
  388. if ( bw != null )
  389. {
  390. int version = 0;
  391. bw.Write(version);
  392. bw.Write((int)mod.meshes.Count);
  393. bw.Write(mod.optimize);
  394. // max number of verts and tris, so we can allocate a single buffer
  395. long[] vals = new long[mod.meshes.Count];
  396. int maxv = 0;
  397. int maxf = 0;
  398. int maxsm = 0;
  399. for ( int i = 0; i < mod.meshes.Count; i++ )
  400. {
  401. if ( mod.meshes[i].vertexCount > maxv )
  402. maxv = mod.meshes[i].vertexCount;
  403. if ( mod.meshes[i].triangles.Length > maxf )
  404. maxf = mod.meshes[i].triangles.Length;
  405. int sub = mod.meshes[i].subMeshCount;
  406. if ( sub > maxsm )
  407. maxsm = sub;
  408. }
  409. int[] smfc = new int[maxsm];
  410. for ( int i = 0; i < mod.meshes.Count; i++ )
  411. {
  412. for ( int s = 0; s < mod.meshes[i].subMeshCount; s++ )
  413. {
  414. int len = mod.meshes[i].GetTriangles(s).Length;
  415. if ( len > smfc[s] )
  416. {
  417. smfc[s] = len;
  418. }
  419. }
  420. }
  421. bw.Write(maxv);
  422. bw.Write(maxf);
  423. bw.Write(maxsm);
  424. for ( int i = 0; i < smfc.Length; i++ )
  425. bw.Write(smfc[i]);
  426. long fp = fs.Position;
  427. for ( int i = 0; i < mod.meshes.Count; i++ )
  428. {
  429. long val = 0;
  430. bw.Write(val);
  431. }
  432. for ( int i = 0; i < mod.meshes.Count; i++ )
  433. {
  434. Mesh ms = mod.meshes[i];
  435. vals[i] = fs.Position;
  436. Vector3[] verts = ms.vertices;
  437. Vector3[] norms = ms.normals;
  438. Vector2[] uvs = ms.uv;
  439. Vector4[] tangents = ms.tangents;
  440. bw.Write(verts.Length);
  441. if ( mod.savenormals )
  442. bw.Write(norms.Length);
  443. else
  444. bw.Write((int)0);
  445. if ( mod.saveuvs )
  446. bw.Write(uvs.Length);
  447. else
  448. bw.Write((int)0);
  449. if ( mod.savetangents )
  450. bw.Write(tangents.Length);
  451. else
  452. bw.Write((int)0);
  453. Vector3 bmin = ms.bounds.min;
  454. Vector3 bmax = ms.bounds.max;
  455. bw.Write(bmin.x);
  456. bw.Write(bmin.y);
  457. bw.Write(bmin.z);
  458. bw.Write(bmax.x);
  459. bw.Write(bmax.y);
  460. bw.Write(bmax.z);
  461. Vector3 msize = ms.bounds.size;
  462. if ( mod.optimize )
  463. {
  464. for ( int v = 0; v < verts.Length; v++ )
  465. {
  466. Vector3 pos = verts[v];
  467. short sb = (short)(((pos.x - bmin.x) / msize.x) * 65535.0f);
  468. bw.Write(sb);
  469. sb = (short)(((pos.y - bmin.y) / msize.y) * 65535.0f);
  470. bw.Write(sb);
  471. sb = (short)(((pos.z - bmin.z) / msize.z) * 65535.0f);
  472. bw.Write(sb);
  473. }
  474. }
  475. else
  476. {
  477. for ( int v = 0; v < verts.Length; v++ )
  478. {
  479. Vector3 pos = verts[v];
  480. bw.Write(pos.x);
  481. bw.Write(pos.y);
  482. bw.Write(pos.z);
  483. }
  484. }
  485. if ( mod.savenormals )
  486. {
  487. if ( mod.optimize )
  488. {
  489. for ( int v = 0; v < norms.Length; v++ )
  490. {
  491. Vector3 pos = norms[v];
  492. sbyte sb = (sbyte)(pos.x * 127.0f);
  493. bw.Write(sb);
  494. sb = (sbyte)(pos.y * 127.0f);
  495. bw.Write(sb);
  496. sb = (sbyte)(pos.z * 127.0f);
  497. bw.Write(sb);
  498. }
  499. }
  500. else
  501. {
  502. for ( int v = 0; v < norms.Length; v++ )
  503. {
  504. Vector3 pos = norms[v];
  505. bw.Write(pos.x);
  506. bw.Write(pos.y);
  507. bw.Write(pos.z);
  508. }
  509. }
  510. }
  511. if ( mod.savetangents )
  512. {
  513. if ( mod.optimize )
  514. {
  515. for ( int v = 0; v < tangents.Length; v++ )
  516. {
  517. Vector4 pos = tangents[v];
  518. sbyte sb = (sbyte)(pos.x * 127.0f);
  519. bw.Write(sb);
  520. sb = (sbyte)(pos.y * 127.0f);
  521. bw.Write(sb);
  522. sb = (sbyte)(pos.z * 127.0f);
  523. bw.Write(sb);
  524. sb = (sbyte)(pos.w * 127.0f);
  525. bw.Write(sb);
  526. }
  527. }
  528. else
  529. {
  530. for ( int v = 0; v < tangents.Length; v++ )
  531. {
  532. Vector4 tan = tangents[v];
  533. bw.Write(tan.x);
  534. bw.Write(tan.y);
  535. bw.Write(tan.z);
  536. bw.Write(tan.w);
  537. }
  538. }
  539. }
  540. if ( mod.saveuvs )
  541. {
  542. if ( mod.optimize )
  543. {
  544. Bounds uvb = MegaCacheUtils.GetBounds(uvs);
  545. bw.Write(uvb.min.x);
  546. bw.Write(uvb.min.y);
  547. bw.Write(uvb.max.x);
  548. bw.Write(uvb.max.y);
  549. for ( int v = 0; v < uvs.Length; v++ )
  550. {
  551. Vector2 pos = uvs[v];
  552. sbyte sb = (sbyte)(((pos.x - uvb.min.x) / uvb.size.x) * 255.0f);
  553. bw.Write(sb);
  554. sb = (sbyte)(((pos.y - uvb.min.y) / uvb.size.y) * 255.0f);
  555. bw.Write(sb);
  556. }
  557. }
  558. else
  559. {
  560. for ( int v = 0; v < uvs.Length; v++ )
  561. {
  562. Vector2 uv = uvs[v];
  563. bw.Write(uv.x);
  564. bw.Write(uv.y);
  565. }
  566. }
  567. }
  568. byte scount = (byte)ms.subMeshCount;
  569. bw.Write(scount);
  570. for ( int s = 0; s < scount; s++ )
  571. {
  572. int[] tris = ms.GetTriangles(s);
  573. bw.Write(tris.Length);
  574. for ( int t = 0; t < tris.Length; t++ )
  575. {
  576. ushort ix = (ushort)tris[t];
  577. bw.Write(ix);
  578. }
  579. }
  580. }
  581. fs.Position = fp;
  582. for ( int i = 0; i < vals.Length; i++ )
  583. bw.Write(vals[i]);
  584. bw.Close();
  585. }
  586. fs.Close();
  587. }
  588. }
  589. Texture2D LoadTexture(string filename)
  590. {
  591. Texture2D tex = null;
  592. if ( HaveTexture(filename) )
  593. return (Texture2D)AssetDatabase.LoadAssetAtPath("Assets/MegaCache/" + Path.GetFileNameWithoutExtension(filename) + ".asset", typeof(Texture2D));
  594. if ( File.Exists(filename) )
  595. {
  596. byte[] buf = File.ReadAllBytes(filename);
  597. tex = new Texture2D(2, 2);
  598. tex.name = Path.GetFileNameWithoutExtension(filename);
  599. tex.LoadImage(buf);
  600. if ( !Directory.Exists("Assets/MegaCache") )
  601. AssetDatabase.CreateFolder("Assets", "MegaCache");
  602. string meshpath = "Assets/MegaCache/" + tex.name + ".asset";
  603. AssetDatabase.CreateAsset(tex, meshpath);
  604. AssetDatabase.SaveAssets();
  605. AssetDatabase.Refresh();
  606. }
  607. return tex;
  608. }
  609. bool HaveTexture(string filename)
  610. {
  611. if ( File.Exists("Assets/MegaCache/" + Path.GetFileNameWithoutExtension(filename) + ".asset") )
  612. return true;
  613. return false;
  614. }
  615. bool HaveMaterial(string name)
  616. {
  617. if ( File.Exists("Assets/MegaCache/" + name + ".mat") )
  618. return true;
  619. return false;
  620. }
  621. }