Files
UltimateFishing/Assets/Scripts/Assembly-CSharp/MegaCacheOBJ.cs
2026-02-21 16:45:37 +08:00

739 lines
16 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
[RequireComponent(typeof(MeshRenderer))]
[AddComponentMenu("MegaFiers/OBJ Cache")]
[ExecuteInEditMode]
[RequireComponent(typeof(MeshFilter))]
public class MegaCacheOBJ : MonoBehaviour
{
public List<Mesh> meshes = new List<Mesh>();
public int frame;
public bool animate;
public float time;
public float speed = 1f;
public float looptime = 5f;
public float fps = 25f;
public MegaCacheRepeatMode loopmode;
public int firstframe;
public int lastframe = 1;
public int skip;
public string lastpath = string.Empty;
public string cachefile = string.Empty;
public int framevertcount;
public int frametricount;
public float scale = 1f;
public bool adjustcoord = true;
public bool buildtangents;
public bool updatecollider;
public bool saveuvs = true;
public bool savenormals = true;
public bool savetangents = true;
public bool optimize = true;
public bool recalcnormals;
public bool update;
public bool loadmtls;
public MegaCacheData datasource;
public MegaCacheImage cacheimage;
public MeshFilter mf;
public int framecount;
public Vector3[] vertcache;
public Vector3[] normcache;
public Vector4[] tangentcache;
public Vector2[] uvcache;
public MegaCacheImageFace[] subs;
public int decformat;
public bool shownormals;
public bool showextras;
public float normallen = 1f;
public bool showdataimport = true;
public bool showanimation = true;
public bool showdata;
public string namesplit = string.Empty;
public string runtimefolder = string.Empty;
private bool optimized;
private int lastreadframe = -1;
private Mesh lastmesh;
private int maxv;
private int maxsm;
private int[] maxsmfc;
private FileStream fs;
private BinaryReader br;
private long[] meshoffs;
public Mesh imagemesh;
private static byte[] buffer;
public bool meshchanged;
private MeshCollider meshCol;
[ContextMenu("Help")]
public void Help()
{
Application.OpenURL("http://www.west-racing.com/mf/?page_id=6226");
}
private void Start()
{
mf = GetComponent<MeshFilter>();
if (!Application.isEditor && datasource == MegaCacheData.File && fs == null)
{
string fileName = Path.GetFileName(cachefile);
string text = Application.dataPath + "/";
if (runtimefolder.Length > 0)
{
text = text + runtimefolder + "/";
}
text += fileName;
OpenCache(text);
}
}
public void ChangeSource(MegaCacheData src)
{
if (src != datasource)
{
CloseCache();
datasource = src;
if (Application.isEditor)
{
UnityEngine.Object.DestroyImmediate(imagemesh);
}
else
{
UnityEngine.Object.Destroy(imagemesh);
}
switch (datasource)
{
case MegaCacheData.File:
OpenCache(cachefile);
break;
case MegaCacheData.Image:
MountImage(cacheimage);
break;
}
update = true;
}
}
private void Update()
{
int num = 0;
switch (datasource)
{
case MegaCacheData.Mesh:
num = meshes.Count - 1;
break;
case MegaCacheData.File:
num = framecount - 1;
break;
case MegaCacheData.Image:
if ((bool)cacheimage && cacheimage.frames != null)
{
num = cacheimage.frames.Count - 1;
}
break;
}
if (num > 0)
{
if (animate)
{
looptime = (float)num / fps;
time += Time.deltaTime * speed;
float num2 = time;
switch (loopmode)
{
case MegaCacheRepeatMode.Loop:
num2 = Mathf.Repeat(time, Mathf.Abs(looptime));
if (looptime < 0f)
{
num2 = looptime - num2;
}
break;
case MegaCacheRepeatMode.PingPong:
num2 = Mathf.PingPong(time, looptime);
break;
case MegaCacheRepeatMode.Clamp:
num2 = Mathf.Clamp(time, 0f, looptime);
break;
}
frame = (int)(num2 / looptime * (float)num);
}
frame = Mathf.Clamp(frame, 0, num);
if (frame != lastframe)
{
meshchanged = true;
}
if (datasource == MegaCacheData.Image && (bool)cacheimage)
{
if (imagemesh == null)
{
imagemesh = new Mesh();
}
if (mf.sharedMesh != imagemesh)
{
ClearMesh();
mf.sharedMesh = imagemesh;
}
cacheimage.GetMesh(imagemesh, frame, this);
}
if (datasource == MegaCacheData.File)
{
GetFrame(frame);
}
if (datasource == MegaCacheData.Mesh && (bool)mf && meshes.Count > 0 && (mf.sharedMesh != meshes[frame] || update))
{
mf.sharedMesh = meshes[frame];
framevertcount = meshes[frame].vertexCount;
}
if (updatecollider && meshchanged)
{
if (meshCol == null)
{
meshCol = GetComponent<MeshCollider>();
}
if (meshCol != null)
{
meshCol.sharedMesh = null;
meshCol.sharedMesh = mf.sharedMesh;
}
}
}
update = false;
meshchanged = false;
}
private void Reset()
{
}
public void AddMesh(Mesh ms)
{
if ((bool)ms)
{
meshes.Add(ms);
}
}
public void DestroyMeshes()
{
for (int i = 0; i < meshes.Count; i++)
{
if (Application.isPlaying)
{
UnityEngine.Object.Destroy(meshes[i]);
}
else
{
UnityEngine.Object.DestroyImmediate(meshes[i]);
}
}
meshes.Clear();
meshes.TrimExcess();
GC.Collect();
ClearMesh();
mf.sharedMesh = new Mesh();
}
public void DestroyImage()
{
if ((bool)cacheimage)
{
if (Application.isEditor)
{
UnityEngine.Object.DestroyImmediate(cacheimage);
}
else
{
UnityEngine.Object.Destroy(cacheimage);
}
cacheimage = null;
}
}
public void ClearMesh()
{
if (Application.isEditor)
{
UnityEngine.Object.DestroyImmediate(mf.sharedMesh);
}
else
{
UnityEngine.Object.Destroy(mf.sharedMesh);
}
mf.sharedMesh = null;
}
public void InitImport()
{
MegaCacheObjImporter.Init();
}
public Mesh LoadFrame(string filename, int frame)
{
Mesh result = null;
char[] separator = new char[10] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
string directoryName = Path.GetDirectoryName(filename);
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(filename);
string[] array;
if (namesplit.Length > 0)
{
array = fileNameWithoutExtension.Split(namesplit[0]);
// string[] array2;
array[0] = array[0] + namesplit[0];
}
else
{
array = fileNameWithoutExtension.Split(separator);
}
if (array.Length > 0)
{
string filename2 = directoryName + "/" + array[0] + frame.ToString("D" + decformat) + ".obj";
result = LoadFrame(filename2);
}
return result;
}
public void LoadMtl(string filename, int frame)
{
char[] separator = new char[10] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
string directoryName = Path.GetDirectoryName(filename);
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(filename);
string[] array;
if (namesplit.Length > 0)
{
array = fileNameWithoutExtension.Split(namesplit[0]);
// string[] array2;
array[0] = array[0] + namesplit[0];
}
else
{
array = fileNameWithoutExtension.Split(separator);
}
if (array.Length > 0)
{
string filename2 = directoryName + "/" + array[0] + frame.ToString("D" + decformat) + ".mtl";
LoadMtl(filename2);
}
}
public void LoadMtl(string filename)
{
if (File.Exists(filename))
{
MegaCacheObjImporter.ImportMtl(filename);
}
}
public Mesh LoadFrame(string filename)
{
Mesh result = null;
if (File.Exists(filename))
{
result = MegaCacheObjImporter.ImportFile(filename, scale, adjustcoord, buildtangents, loadmtls, optimize, recalcnormals);
}
return result;
}
public void MountImage(MegaCacheImage image)
{
if ((bool)image)
{
subs = new MegaCacheImageFace[image.maxsm];
for (int i = 0; i < image.maxsm; i++)
{
MegaCacheImageFace megaCacheImageFace = new MegaCacheImageFace();
megaCacheImageFace.max = image.smfc[i];
megaCacheImageFace.tris = new int[megaCacheImageFace.max];
subs[i] = megaCacheImageFace;
}
vertcache = new Vector3[image.maxv];
normcache = new Vector3[image.maxv];
tangentcache = new Vector4[image.maxv];
uvcache = new Vector2[image.maxv];
}
}
public void OpenCache(string filename)
{
if (filename.Length == 0)
{
return;
}
fs = new FileStream(filename, FileMode.Open);
if (fs == null)
{
return;
}
br = new BinaryReader(fs);
if (br == null)
{
return;
}
if (br.ReadInt32() == 0)
{
framecount = br.ReadInt32();
optimized = br.ReadBoolean();
maxv = br.ReadInt32();
br.ReadInt32();
maxsm = br.ReadInt32();
subs = new MegaCacheImageFace[maxsm];
for (int i = 0; i < maxsm; i++)
{
MegaCacheImageFace megaCacheImageFace = new MegaCacheImageFace();
megaCacheImageFace.max = br.ReadInt32();
megaCacheImageFace.tris = new int[megaCacheImageFace.max];
subs[i] = megaCacheImageFace;
}
}
vertcache = new Vector3[maxv];
normcache = new Vector3[maxv];
tangentcache = new Vector4[maxv];
uvcache = new Vector2[maxv];
if (buffer == null || buffer.Length < maxv * 16)
{
buffer = new byte[maxv * 16];
}
meshoffs = new long[framecount];
for (int j = 0; j < framecount; j++)
{
meshoffs[j] = br.ReadInt64();
}
ClearMesh();
Mesh sharedMesh = new Mesh();
mf.sharedMesh = sharedMesh;
update = true;
}
private void OnDestroy()
{
CloseCache();
}
private void OnDrawGizmosSelected()
{
if (shownormals)
{
Vector3[] vertices = mf.sharedMesh.vertices;
Vector3[] normals = mf.sharedMesh.normals;
Gizmos.color = Color.red;
Gizmos.matrix = base.transform.localToWorldMatrix;
float num = normallen * 0.01f;
Color black = Color.black;
for (int i = 0; i < framevertcount; i++)
{
black.r = normals[i].x;
black.g = normals[i].y;
black.b = normals[i].z;
Gizmos.color = black;
Gizmos.DrawRay(vertices[i], normals[i] * num);
}
Gizmos.matrix = Matrix4x4.identity;
}
}
private void GetFrame(int fnum)
{
if (br == null)
{
OpenCache(cachefile);
}
GetFrame(fnum, mf.sharedMesh);
}
public void GetFrameRef(int fnum, Mesh _mesh)
{
if (br == null)
{
OpenCache(cachefile);
update = true;
}
GetFrame(fnum, _mesh);
}
public void GetFrame(int fnum, Mesh mesh)
{
if (fnum != lastreadframe || update || lastmesh == null)
{
MakeMeshFromFrame(fnum, mesh);
lastreadframe = fnum;
lastmesh = mesh;
}
else if (fnum == lastreadframe && mesh != lastmesh && lastmesh != null)
{
mesh.bounds = lastmesh.bounds;
mesh.subMeshCount = lastmesh.subMeshCount;
mesh.vertices = lastmesh.vertices;
mesh.normals = lastmesh.normals;
mesh.uv = lastmesh.uv;
mesh.tangents = lastmesh.tangents;
for (int i = 0; i < lastmesh.subMeshCount; i++)
{
mesh.SetTriangles(lastmesh.GetTriangles(i), i);
}
}
}
public void MakeMeshFromFrame(int fnum, Mesh mesh)
{
if (br == null)
{
return;
}
fs.Position = meshoffs[fnum];
int num = br.ReadInt32();
int num2 = br.ReadInt32();
int num3 = br.ReadInt32();
int num4 = br.ReadInt32();
Vector3 vector = default(Vector3);
vector.x = br.ReadSingle();
vector.y = br.ReadSingle();
vector.z = br.ReadSingle();
Vector3 vector2 = default(Vector3);
vector2.x = br.ReadSingle();
vector2.y = br.ReadSingle();
vector2.z = br.ReadSingle();
Vector3 vector3 = (vector2 - vector) * 1.5259022E-05f;
mesh.bounds.SetMinMax(vector, vector2);
float num5 = 1f / 127f;
if (!optimized)
{
br.Read(buffer, 0, num * 12);
for (int i = 0; i < num; i++)
{
int num6 = i * 12;
vertcache[i].x = BitConverter.ToSingle(buffer, num6);
vertcache[i].y = BitConverter.ToSingle(buffer, num6 + 4);
vertcache[i].z = BitConverter.ToSingle(buffer, num6 + 8);
}
}
else
{
br.Read(buffer, 0, num * 6);
for (int j = 0; j < num; j++)
{
int num7 = j * 6;
vertcache[j].x = vector.x + (float)(int)BitConverter.ToUInt16(buffer, num7) * vector3.x;
vertcache[j].y = vector.y + (float)(int)BitConverter.ToUInt16(buffer, num7 + 2) * vector3.y;
vertcache[j].z = vector.z + (float)(int)BitConverter.ToUInt16(buffer, num7 + 4) * vector3.z;
}
}
if (!optimized)
{
br.Read(buffer, 0, num2 * 12);
for (int k = 0; k < num2; k++)
{
int num8 = k * 12;
normcache[k].x = BitConverter.ToSingle(buffer, num8);
normcache[k].y = BitConverter.ToSingle(buffer, num8 + 4);
normcache[k].z = BitConverter.ToSingle(buffer, num8 + 8);
}
}
else
{
br.Read(buffer, 0, num2 * 3);
for (int l = 0; l < num2; l++)
{
int num9 = l * 3;
normcache[l].x = (float)(sbyte)buffer[num9] * num5;
normcache[l].y = (float)(sbyte)buffer[num9 + 1] * num5;
normcache[l].z = (float)(sbyte)buffer[num9 + 2] * num5;
}
}
if (!optimized)
{
br.Read(buffer, 0, num4 * 16);
for (int m = 0; m < num4; m++)
{
int num10 = m * 16;
tangentcache[m].x = BitConverter.ToSingle(buffer, num10);
tangentcache[m].y = BitConverter.ToSingle(buffer, num10 + 4);
tangentcache[m].z = BitConverter.ToSingle(buffer, num10 + 8);
tangentcache[m].w = BitConverter.ToSingle(buffer, num10 + 12);
}
}
else
{
br.Read(buffer, 0, num4 * 4);
for (int n = 0; n < num4; n++)
{
tangentcache[n].x = (float)(sbyte)buffer[n * 4] * num5;
tangentcache[n].y = (float)(sbyte)buffer[n * 4 + 1] * num5;
tangentcache[n].z = (float)(sbyte)buffer[n * 4 + 2] * num5;
tangentcache[n].w = (float)(sbyte)buffer[n * 4 + 3] * num5;
}
}
if (!optimized)
{
br.Read(buffer, 0, num3 * 8);
for (int num11 = 0; num11 < num3; num11++)
{
int num12 = num11 * 8;
uvcache[num11].x = BitConverter.ToSingle(buffer, num12);
uvcache[num11].y = BitConverter.ToSingle(buffer, num12 + 4);
}
}
else
{
Vector2 vector4 = default(Vector2);
vector4.x = br.ReadSingle();
vector4.y = br.ReadSingle();
Vector2 vector5 = default(Vector2);
vector5.x = br.ReadSingle();
vector5.y = br.ReadSingle();
Vector2 vector6 = (vector5 - vector4) * 0.003921569f;
br.Read(buffer, 0, num3 * 2);
for (int num13 = 0; num13 < num3; num13++)
{
int num14 = num13 * 2;
uvcache[num13].x = vector4.x + (float)(int)buffer[num14] * vector6.x;
uvcache[num13].y = vector4.y + (float)(int)buffer[num14 + 1] * vector6.y;
}
}
byte b = (byte)(mesh.subMeshCount = br.ReadByte());
mesh.vertices = vertcache;
if (num2 > 0)
{
mesh.normals = normcache;
}
if (num3 > 0)
{
mesh.uv = uvcache;
}
if (num4 > 0)
{
mesh.tangents = tangentcache;
}
for (int num16 = 0; num16 < b; num16++)
{
int num17 = br.ReadInt32();
br.Read(buffer, 0, num17 * 2);
for (int num18 = 0; num18 < num17; num18++)
{
subs[num16].tris[num18] = BitConverter.ToUInt16(buffer, num18 * 2);
}
for (int num19 = num17; num19 < subs[num16].max; num19++)
{
subs[num16].tris[num19] = subs[num16].tris[num17];
}
}
for (int num20 = 0; num20 < b; num20++)
{
mesh.SetTriangles(subs[num20].tris, num20);
}
mesh.RecalculateBounds();
}
public void CloseCache()
{
if (br != null)
{
br = null;
}
if (fs != null)
{
fs = null;
}
buffer = null;
GC.Collect();
}
public void CreateImageFromCacheFile()
{
if (br == null)
{
OpenCache(cachefile);
}
if (br != null)
{
if ((bool)cacheimage)
{
DestroyImage();
}
MegaCacheImage megaCacheImage = ScriptableObject.CreateInstance<MegaCacheImage>();
megaCacheImage.maxv = maxv;
megaCacheImage.maxsm = maxsm;
megaCacheImage.smfc = new int[maxsm];
for (int i = 0; i < maxsm; i++)
{
megaCacheImage.smfc[i] = subs[i].max;
}
Mesh mesh = new Mesh();
for (int j = 0; j < framecount; j++)
{
MakeMeshFromFrame(j, mesh);
MegaCacheImageFrame item = MegaCacheImage.CreateImageFrame(mesh);
megaCacheImage.frames.Add(item);
}
cacheimage = megaCacheImage;
ChangeSource(MegaCacheData.Image);
if (Application.isEditor)
{
UnityEngine.Object.DestroyImmediate(mesh);
}
else
{
UnityEngine.Object.Destroy(mesh);
}
mesh = null;
GC.Collect();
}
}
}