299 lines
11 KiB
C#
299 lines
11 KiB
C#
// Warning: Some assembly references could not be resolved automatically. This might lead to incorrect decompilation of some parts,
|
|
// for ex. property getter/setter access. To get optimal decompilation results, please manually add the missing references to the list of loaded assemblies.
|
|
// EdenAutoMorpherScript, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
|
|
// Eden.AutoMorpher.profile.ProfileLoader
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Text;
|
|
using Eden.AutoMorpher;
|
|
using Eden.AutoMorpher.profile;
|
|
using UnityEngine;
|
|
|
|
public class ProfileLoader
|
|
{
|
|
private ProfileData loadedProfileData;
|
|
|
|
private const int HEX32_W = 8;
|
|
|
|
public List<string> GetProfileList()
|
|
{
|
|
ProfileUtils profileUtils = new ProfileUtils();
|
|
string text = Path.Combine(Application.dataPath, profileUtils.GetProfileBasePath());
|
|
List<string> list = new List<string>();
|
|
if (!Directory.Exists(text))
|
|
{
|
|
Debug.LogWarning("[ProfileUtils] Profile base path does not exist: " + text);
|
|
return list;
|
|
}
|
|
string[] directories = Directory.GetDirectories(text);
|
|
foreach (string text2 in directories)
|
|
{
|
|
string fileName = Path.GetFileName(text2);
|
|
if (!string.IsNullOrEmpty(fileName))
|
|
{
|
|
string path = Path.Combine(text2, fileName + ".json");
|
|
string path2 = Path.Combine(text2, fileName + ".eb");
|
|
if (File.Exists(path) && File.Exists(path2))
|
|
{
|
|
list.Add(fileName);
|
|
}
|
|
}
|
|
}
|
|
return list;
|
|
}
|
|
|
|
public ProfileData LoadProfileData(string profileName)
|
|
{
|
|
ProfileUtils profileUtils = new ProfileUtils();
|
|
string path = Path.Combine(Application.dataPath, profileUtils.GetProfileBasePath());
|
|
path = Path.Combine(path, profileName);
|
|
path = Path.Combine(path, profileName + ".json");
|
|
if (string.IsNullOrWhiteSpace(path))
|
|
{
|
|
throw new AutoMorpherException("Profile File Path is Invalid", "[ProfileLoader] LoadProfileData\n - Profile Path is null, empty, or whitespace");
|
|
}
|
|
if (!File.Exists(path))
|
|
{
|
|
throw new AutoMorpherException("Profile File Does Not Exist", "[ProfileLoader] LoadProfileData\n - profile file does not exist\n - path : " + path);
|
|
}
|
|
string json = File.ReadAllText(path);
|
|
loadedProfileData = JsonUtility.FromJson<ProfileData>(json);
|
|
if (loadedProfileData == null)
|
|
{
|
|
throw new AutoMorpherException("Failed to Load Profile Data", "[ProfileLoader] LoadProfileData\n - Can't Load Profile Data\n - Please place a valid profile data file at " + path);
|
|
}
|
|
return loadedProfileData;
|
|
}
|
|
|
|
public BvhTriangleMesh LoadBvhWithRootTransform(Transform rootTransform, string profileName)
|
|
{
|
|
ProfileUtils profileUtils = new ProfileUtils();
|
|
string path = Path.Combine(Application.dataPath, profileUtils.GetProfileBasePath());
|
|
path = Path.Combine(path, profileName);
|
|
path = Path.Combine(path, profileName + ".eb");
|
|
if (rootTransform == null)
|
|
{
|
|
throw new AutoMorpherException("Root Transform is Null", "[ProfileLoader] LoadBvhWithRootTransform\n - rootTransform is null");
|
|
}
|
|
if (string.IsNullOrEmpty(path))
|
|
{
|
|
throw new AutoMorpherException("Profile BVH Path is Invalid", "[ProfileLoader] LoadBvhWithRootTransform\n - profileBvhPath is null or empty");
|
|
}
|
|
int version;
|
|
ProfileBVH profileBVH = LoadProfileBVHData(path, out version);
|
|
if (profileBVH == null || profileBVH.vertices == null || profileBVH.datas == null || profileBVH.nodes == null || profileBVH.dataIndices == null)
|
|
{
|
|
throw new AutoMorpherException("Profile BVH Data is Invalid", "[ProfileLoader] LoadBvhWithRootTransform\n - profile or one of its internal data fields is null");
|
|
}
|
|
Matrix4x4 localToWorldMatrix = rootTransform.localToWorldMatrix;
|
|
int num = profileBVH.datas.Length;
|
|
BvhTriangleMesh bvhTriangleMesh = new BvhTriangleMesh
|
|
{
|
|
triangles = new BvhTriangle[num],
|
|
triIndices = new int[profileBVH.dataIndices.Length],
|
|
nodes = new BvhNode[profileBVH.nodes.Length]
|
|
};
|
|
for (int i = 0; i < num; i++)
|
|
{
|
|
profileBVHData profileBVHData2 = profileBVH.datas[i];
|
|
Vector3 point = profileBVH.vertices[profileBVHData2.verA];
|
|
Vector3 point2 = profileBVH.vertices[profileBVHData2.verB];
|
|
Vector3 point3 = profileBVH.vertices[profileBVHData2.verC];
|
|
Vector3 a = localToWorldMatrix.MultiplyPoint3x4(point);
|
|
Vector3 b = localToWorldMatrix.MultiplyPoint3x4(point2);
|
|
Vector3 c = localToWorldMatrix.MultiplyPoint3x4(point3);
|
|
Vector3 normal = ComputeTriangleNormal(a, b, c);
|
|
bvhTriangleMesh.triangles[i] = new BvhTriangle
|
|
{
|
|
a = a,
|
|
b = b,
|
|
c = c,
|
|
normal = normal,
|
|
mainHumanBone = HumanBodyBones.LastBone
|
|
};
|
|
}
|
|
Array.Copy(profileBVH.dataIndices, bvhTriangleMesh.triIndices, profileBVH.dataIndices.Length);
|
|
for (int j = 0; j < profileBVH.nodes.Length; j++)
|
|
{
|
|
profileBVHNode profileBVHNode2 = profileBVH.nodes[j];
|
|
bvhTriangleMesh.nodes[j] = new BvhNode
|
|
{
|
|
isLeaf = profileBVHNode2.isLeaf,
|
|
leftChild = profileBVHNode2.leftChild,
|
|
rightChild = profileBVHNode2.rightChild,
|
|
start = profileBVHNode2.start,
|
|
count = profileBVHNode2.count,
|
|
bounds = TransformBoundsToWorldAABB(localToWorldMatrix, profileBVHNode2.bounds)
|
|
};
|
|
}
|
|
return bvhTriangleMesh;
|
|
}
|
|
|
|
private ProfileBVH LoadProfileBVHData(string path, out int version)
|
|
{
|
|
version = 0;
|
|
int num = 0;
|
|
if (!File.Exists(path))
|
|
{
|
|
throw new AutoMorpherException("Profile BVH File Not Found", "[ProfileLoader] LoadProfileBVHData\n - file not found\n - path : " + path);
|
|
}
|
|
string text = File.ReadAllText(path, Encoding.UTF8);
|
|
int num2 = 0;
|
|
ProfileUtils profileUtils = new ProfileUtils();
|
|
string profileMagic = profileUtils.GetProfileMagic();
|
|
if (text.Length < profileMagic.Length || text.Substring(0, profileMagic.Length) != profileMagic)
|
|
{
|
|
throw new AutoMorpherException("Profile BVH Magic Mismatch", "[ProfileLoader] LoadProfileBVHData\n - magic string mismatch\n - invalid or corrupted BVH file");
|
|
}
|
|
num2 += profileMagic.Length;
|
|
version = ReadHexIntSafe(text, ref num2);
|
|
num = ReadHexIntSafe(text, ref num2);
|
|
int num3 = ReadHexIntSafe(text, ref num2);
|
|
int num4 = ReadHexIntSafe(text, ref num2);
|
|
int num5 = ReadHexIntSafe(text, ref num2);
|
|
int num6 = ReadHexIntSafe(text, ref num2);
|
|
if (num3 < 0 || num4 < 0 || num5 < 0 || num6 < 0)
|
|
{
|
|
throw new AutoMorpherException("Profile BVH Count Data is Invalid", "[ProfileLoader] LoadProfileBVHData\n - one or more count values are negative");
|
|
}
|
|
Vector3[] array = new Vector3[num3];
|
|
for (int i = 0; i < num3; i++)
|
|
{
|
|
array[i] = ReadHexVec3Safe(text, ref num2);
|
|
}
|
|
int version2;
|
|
int countInFile;
|
|
BaseKey3[] array2 = new ProfileUtils_VertexUtil().LoadTable(profileUtils.GetBaseDataPath(), out version2, out countInFile);
|
|
if (array2 == null || array2.Length == 0)
|
|
{
|
|
throw new AutoMorpherException("Profile BVH Base Vertex Table is Invalid", "[ProfileLoader] LoadProfileBVHData\n - base vertex table is null or empty");
|
|
}
|
|
ProfileUtil_IndexUtil profileUtil_IndexUtil = new ProfileUtil_IndexUtil();
|
|
profileUtil_IndexUtil.Build(num);
|
|
Vector3[] array3 = new Vector3[num3];
|
|
profileUtil_IndexUtil.DecodeInto(array, array3);
|
|
Vector3[] array4 = new Vector3[num3];
|
|
for (int j = 0; j < num3; j++)
|
|
{
|
|
array4[j] = TransformVec3(array3[j], array2[j % array2.Length]);
|
|
}
|
|
ProfileBVH profileBVH = new ProfileBVH
|
|
{
|
|
vertices = new List<Vector3>(num3),
|
|
datas = new profileBVHData[num4],
|
|
nodes = new profileBVHNode[num5],
|
|
dataIndices = new int[num6]
|
|
};
|
|
profileBVH.vertices.AddRange(array4);
|
|
for (int k = 0; k < num4; k++)
|
|
{
|
|
profileBVH.datas[k] = new profileBVHData
|
|
{
|
|
verA = ReadHexIntSafe(text, ref num2),
|
|
verB = ReadHexIntSafe(text, ref num2),
|
|
verC = ReadHexIntSafe(text, ref num2)
|
|
};
|
|
}
|
|
for (int l = 0; l < num5; l++)
|
|
{
|
|
Vector3 center = ReadHexVec3Safe(text, ref num2);
|
|
Vector3 vector = ReadHexVec3Safe(text, ref num2);
|
|
profileBVH.nodes[l] = new profileBVHNode
|
|
{
|
|
bounds = new Bounds(center, vector * 2f),
|
|
leftChild = ReadHexIntSafe(text, ref num2),
|
|
rightChild = ReadHexIntSafe(text, ref num2),
|
|
start = ReadHexIntSafe(text, ref num2),
|
|
count = ReadHexIntSafe(text, ref num2),
|
|
isLeaf = (num2 < text.Length && text[num2++] == '1')
|
|
};
|
|
}
|
|
for (int m = 0; m < num6; m++)
|
|
{
|
|
profileBVH.dataIndices[m] = ReadHexIntSafe(text, ref num2);
|
|
}
|
|
return profileBVH;
|
|
}
|
|
|
|
private int ReadHexIntSafe(string s, ref int p)
|
|
{
|
|
if (p + 8 > s.Length)
|
|
{
|
|
p = s.Length;
|
|
throw new AutoMorpherException("Profile BVH ReadHexInt Out of Range", "[ProfileBVH] ReadHexIntSafe\n - read position exceeds string length");
|
|
}
|
|
uint result = Convert.ToUInt32(s.Substring(p, 8), 16);
|
|
p += 8;
|
|
return (int)result;
|
|
}
|
|
|
|
private Vector3 ReadHexVec3Safe(string s, ref int p)
|
|
{
|
|
return new Vector3(ReadHexFloatSafe(s, ref p), ReadHexFloatSafe(s, ref p), ReadHexFloatSafe(s, ref p));
|
|
}
|
|
|
|
private float ReadHexFloatSafe(string s, ref int p)
|
|
{
|
|
if (p + 8 > s.Length)
|
|
{
|
|
p = s.Length;
|
|
throw new AutoMorpherException("Profile BVH ReadHexFloat Out of Range", "[ProfileBVH] ReadHexFloat\n - read position exceeds string length");
|
|
}
|
|
uint value = Convert.ToUInt32(s.Substring(p, 8), 16);
|
|
p += 8;
|
|
return BitConverter.Int32BitsToSingle((int)value);
|
|
}
|
|
|
|
private Vector3 TransformVec3(Vector3 v, BaseKey3 k)
|
|
{
|
|
return new Vector3(TransformFloatBits(v.x, k.x), TransformFloatBits(v.y, k.y), TransformFloatBits(v.z, k.z));
|
|
}
|
|
|
|
private float TransformFloatBits(float a, uint keyBits)
|
|
{
|
|
return BitConverter.Int32BitsToSingle(BitConverter.SingleToInt32Bits(a) ^ (int)keyBits);
|
|
}
|
|
|
|
private Vector3 ComputeTriangleNormal(Vector3 a, Vector3 b, Vector3 c)
|
|
{
|
|
Vector3 vector = Vector3.Cross(b - a, c - a);
|
|
float magnitude = vector.magnitude;
|
|
if (magnitude > 1E-08f)
|
|
{
|
|
return vector / magnitude;
|
|
}
|
|
return Vector3.up;
|
|
}
|
|
|
|
private Bounds TransformBoundsToWorldAABB(Matrix4x4 l2w, Bounds localBounds)
|
|
{
|
|
Vector3 center = localBounds.center;
|
|
Vector3 extents = localBounds.extents;
|
|
Vector3 vector = l2w.MultiplyPoint3x4(center + new Vector3(0f - extents.x, 0f - extents.y, 0f - extents.z));
|
|
Vector3 p = l2w.MultiplyPoint3x4(center + new Vector3(0f - extents.x, 0f - extents.y, extents.z));
|
|
Vector3 p2 = l2w.MultiplyPoint3x4(center + new Vector3(0f - extents.x, extents.y, 0f - extents.z));
|
|
Vector3 p3 = l2w.MultiplyPoint3x4(center + new Vector3(0f - extents.x, extents.y, extents.z));
|
|
Vector3 p4 = l2w.MultiplyPoint3x4(center + new Vector3(extents.x, 0f - extents.y, 0f - extents.z));
|
|
Vector3 p5 = l2w.MultiplyPoint3x4(center + new Vector3(extents.x, 0f - extents.y, extents.z));
|
|
Vector3 p6 = l2w.MultiplyPoint3x4(center + new Vector3(extents.x, extents.y, 0f - extents.z));
|
|
Vector3 p7 = l2w.MultiplyPoint3x4(center + new Vector3(extents.x, extents.y, extents.z));
|
|
Vector3 min = vector;
|
|
Vector3 max = vector;
|
|
Encapsulate(ref min, ref max, p);
|
|
Encapsulate(ref min, ref max, p2);
|
|
Encapsulate(ref min, ref max, p3);
|
|
Encapsulate(ref min, ref max, p4);
|
|
Encapsulate(ref min, ref max, p5);
|
|
Encapsulate(ref min, ref max, p6);
|
|
Encapsulate(ref min, ref max, p7);
|
|
return new Bounds((min + max) * 0.5f, max - min);
|
|
}
|
|
|
|
private void Encapsulate(ref Vector3 min, ref Vector3 max, Vector3 p)
|
|
{
|
|
min = Vector3.Min(min, p);
|
|
max = Vector3.Max(max, p);
|
|
}
|
|
}
|