219 lines
10 KiB
C#
219 lines
10 KiB
C#
// Decompiled with JetBrains decompiler
|
|
// Type: Eden.AutoMorpher.MeshClassifier
|
|
// Assembly: EdenAutoMorpherScript, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
|
|
// MVID: D39968B3-E151-4276-BDB4-E82752BBAFF0
|
|
// Assembly location: D:\dev\AutoMorpher\Assets\@Eden_Tools\Eden_AutoMorpher\Script\EdenAutoMorpherScript.dll
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
namespace Eden.AutoMorpher
|
|
{
|
|
public class MeshClassifier
|
|
{
|
|
private HumanBodyBones[] bodyBones;
|
|
private HumanBodyBones[] headBones;
|
|
|
|
public SkinnedMeshRenderer GetBodyMesh(Transform root, Animator animator)
|
|
{
|
|
List<Transform> humanBoneTransforms = this.HumanBodyBonesTrsnforms(this.bodyBones, animator);
|
|
if (humanBoneTransforms.Count == this.bodyBones.Length)
|
|
return this.GetBoneMatchedMesh(root, humanBoneTransforms);
|
|
if (AutoMorpherDev.isDeveloperMode)
|
|
Debug.LogWarning((object)"[Body Mesh] Animator Bone is not enough");
|
|
return (SkinnedMeshRenderer)null;
|
|
}
|
|
|
|
public SkinnedMeshRenderer GetHeadMesh(Transform root, Animator animator)
|
|
{
|
|
List<Transform> humanBoneTransforms = this.HumanBodyBonesTrsnforms(this.headBones, animator);
|
|
return humanBoneTransforms.Count != this.headBones.Length ? (SkinnedMeshRenderer)null : this.GetBoneMatchedMesh(root, humanBoneTransforms);
|
|
}
|
|
|
|
private List<Transform> HumanBodyBonesTrsnforms(
|
|
HumanBodyBones[] humanBonesList,
|
|
Animator animator)
|
|
{
|
|
List<Transform> transformList = new List<Transform>();
|
|
List<HumanBodyBones> values = new List<HumanBodyBones>();
|
|
foreach (int humanBones in humanBonesList)
|
|
{
|
|
HumanBodyBones humanBodyBones = (HumanBodyBones)humanBones;
|
|
Transform boneTransform = animator.GetBoneTransform(humanBodyBones);
|
|
if (Object.op_Equality((Object)boneTransform, (Object)null))
|
|
values.Add(humanBodyBones);
|
|
else
|
|
transformList.Add(boneTransform);
|
|
}
|
|
if (values.Count > 0)
|
|
throw new AutoMorpherException("[Body Mesh Finding] Required Humanoid Bones are Missing", $"[BodyMeshUtil] HumanBodyBonesTrsnforms\n - Missing Humanoid Bones: [{string.Join<HumanBodyBones>(", ", (IEnumerable<HumanBodyBones>)values)}]\n - Animator Humanoid mapping may be broken\n - Please check whether the missing humanoid bones are correctly assigned in [Animator → Avatar → Configure].");
|
|
return transformList;
|
|
}
|
|
|
|
private SkinnedMeshRenderer GetBoneMatchedMesh(
|
|
Transform root,
|
|
List<Transform> humanBoneTransforms)
|
|
{
|
|
foreach (SkinnedMeshRenderer componentsInChild in ((Component)root).GetComponentsInChildren<SkinnedMeshRenderer>(false))
|
|
{
|
|
bool flag = true;
|
|
HashSet<Transform> activeBones = this.GetActiveBones(componentsInChild);
|
|
if (AutoMorpherDev.isDeveloperMode)
|
|
Debug.Log((object)$"[Body Mesh] {((Object)((Component)componentsInChild).gameObject).name} have bone Set {activeBones.Count}");
|
|
foreach (Transform humanBoneTransform in humanBoneTransforms)
|
|
{
|
|
if (!activeBones.Contains(humanBoneTransform) && !this.BoneExistsByPosition(humanBoneTransform, activeBones))
|
|
{
|
|
flag = false;
|
|
if (AutoMorpherDev.isDeveloperMode)
|
|
{
|
|
Debug.Log((object)$"[Body Mesh] {((Object)((Component)componentsInChild).gameObject).name} Doesn't hav bone {((Object)humanBoneTransform).name}");
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
if (flag)
|
|
return componentsInChild;
|
|
}
|
|
return (SkinnedMeshRenderer)null;
|
|
}
|
|
|
|
private bool BoneExistsByPosition(
|
|
Transform boneToCheck,
|
|
HashSet<Transform> smrBoneSet,
|
|
float posTolerance = 0.0001f)
|
|
{
|
|
foreach (Transform smrBone in smrBoneSet)
|
|
{
|
|
Vector3 vector3 = Vector3.op_Subtraction(smrBone.position, boneToCheck.position);
|
|
if ((double)((Vector3)ref vector3).sqrMagnitude <= (double)posTolerance * (double)posTolerance)
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public HashSet<Transform> GetActiveBones(SkinnedMeshRenderer smr, float weightThreshold = 0.0001f)
|
|
{
|
|
Mesh sharedMesh = smr.sharedMesh;
|
|
if (Object.op_Equality((Object)sharedMesh, (Object)null))
|
|
{
|
|
Debug.LogWarning((object)"SkinnedMeshRenderer에 연결된 Mesh가 없습니다.");
|
|
return new HashSet<Transform>();
|
|
}
|
|
Transform[] bones = smr.bones;
|
|
BoneWeight[] boneWeights = sharedMesh.boneWeights;
|
|
HashSet<int> intSet = new HashSet<int>();
|
|
foreach (BoneWeight boneWeight in boneWeights)
|
|
{
|
|
if ((double)((BoneWeight)ref boneWeight).weight0 > (double)weightThreshold)
|
|
intSet.Add(((BoneWeight)ref boneWeight).boneIndex0);
|
|
if ((double)((BoneWeight)ref boneWeight).weight1 > (double)weightThreshold)
|
|
intSet.Add(((BoneWeight)ref boneWeight).boneIndex1);
|
|
if ((double)((BoneWeight)ref boneWeight).weight2 > (double)weightThreshold)
|
|
intSet.Add(((BoneWeight)ref boneWeight).boneIndex2);
|
|
if ((double)((BoneWeight)ref boneWeight).weight3 > (double)weightThreshold)
|
|
intSet.Add(((BoneWeight)ref boneWeight).boneIndex3);
|
|
}
|
|
HashSet<Transform> activeBones = new HashSet<Transform>();
|
|
foreach (int index in intSet)
|
|
{
|
|
if (index >= 0 && index < bones.Length)
|
|
activeBones.Add(bones[index]);
|
|
}
|
|
return activeBones;
|
|
}
|
|
|
|
public Dictionary<HumanBodyBones, HashSet<Transform>> MeshHumanoidBoneMatcher(
|
|
Animator animator,
|
|
IReadOnlyList<SkinnedMeshRenderer> bodyMeshes,
|
|
float posTolerance = 0.0001f,
|
|
float weightThreshold = 0.0001f)
|
|
{
|
|
Dictionary<HumanBodyBones, HashSet<Transform>> dictionary = new Dictionary<HumanBodyBones, HashSet<Transform>>();
|
|
if (Object.op_Equality((Object)animator, (Object)null))
|
|
throw new AutoMorpherException("Animator is Missing", "[MeshHumanoidBoneMatcher] MeshHumanoidBoneMatcher\n - animator is null");
|
|
HashSet<Transform> smrBoneSet = new HashSet<Transform>();
|
|
if (bodyMeshes != null)
|
|
{
|
|
foreach (SkinnedMeshRenderer bodyMesh in (IEnumerable<SkinnedMeshRenderer>)bodyMeshes)
|
|
{
|
|
if (!Object.op_Equality((Object)bodyMesh, (Object)null))
|
|
{
|
|
foreach (Transform activeBone in this.GetActiveBones(bodyMesh, weightThreshold))
|
|
{
|
|
if (Object.op_Inequality((Object)activeBone, (Object)null))
|
|
smrBoneSet.Add(activeBone);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for (int index = 0; index < 55; ++index)
|
|
{
|
|
HumanBodyBones key = (HumanBodyBones)index;
|
|
Transform boneTransform = animator.GetBoneTransform(key);
|
|
if (!Object.op_Equality((Object)boneTransform, (Object)null))
|
|
{
|
|
HashSet<Transform> transformSet = new HashSet<Transform>();
|
|
transformSet.Add(boneTransform);
|
|
foreach (Transform transform in this.FindBonesByPosition(boneTransform, smrBoneSet, posTolerance))
|
|
transformSet.Add(transform);
|
|
dictionary[key] = transformSet;
|
|
}
|
|
}
|
|
return dictionary;
|
|
}
|
|
|
|
private List<Transform> FindBonesByPosition(
|
|
Transform boneToCheck,
|
|
HashSet<Transform> smrBoneSet,
|
|
float posTolerance = 0.0001f)
|
|
{
|
|
List<Transform> bonesByPosition = new List<Transform>();
|
|
if (Object.op_Equality((Object)boneToCheck, (Object)null))
|
|
return bonesByPosition;
|
|
float num = posTolerance * posTolerance;
|
|
Vector3 position = boneToCheck.position;
|
|
foreach (Transform smrBone in smrBoneSet)
|
|
{
|
|
if (!Object.op_Equality((Object)smrBone, (Object)null) && !Object.op_Equality((Object)smrBone, (Object)boneToCheck) && this.NameMatches(((Object)((Component)smrBone).gameObject).name, ((Object)((Component)boneToCheck).gameObject).name))
|
|
{
|
|
Vector3 vector3 = Vector3.op_Subtraction(smrBone.position, position);
|
|
if ((double)((Vector3)ref vector3).sqrMagnitude <= (double)num)
|
|
bonesByPosition.Add(smrBone);
|
|
}
|
|
}
|
|
return bonesByPosition;
|
|
}
|
|
|
|
private string[] TokenizeBoneName(string name)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(name))
|
|
return Array.Empty<string>();
|
|
char[] separator = new char[5]
|
|
{
|
|
'-',
|
|
'_',
|
|
':',
|
|
'.',
|
|
'|'
|
|
};
|
|
name = name.Trim();
|
|
return name.Split(separator, StringSplitOptions.RemoveEmptyEntries);
|
|
}
|
|
|
|
private bool NameMatches(string boneToCheckName, string candidateName)
|
|
{
|
|
string[] strArray1 = this.TokenizeBoneName(boneToCheckName);
|
|
string[] strArray2 = this.TokenizeBoneName(candidateName);
|
|
return strArray1.Length != 0 && strArray2.Length != 0 && strArray1[0].Equals(strArray2[0], StringComparison.OrdinalIgnoreCase) && (strArray1.Length <= 1 || strArray2.Length <= 1 || strArray1[1].Equals(strArray2[1], StringComparison.OrdinalIgnoreCase));
|
|
}
|
|
|
|
public MeshClassifier()
|
|
{
|
|
// ISSUE: unable to decompile the method.
|
|
}
|
|
}
|
|
}
|