summaryrefslogtreecommitdiff
path: root/Assets/ThirdParty/VRM/VRM/UniHumanoid/Scripts/IO/BvhImporterContext.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Assets/ThirdParty/VRM/VRM/UniHumanoid/Scripts/IO/BvhImporterContext.cs')
-rw-r--r--Assets/ThirdParty/VRM/VRM/UniHumanoid/Scripts/IO/BvhImporterContext.cs235
1 files changed, 235 insertions, 0 deletions
diff --git a/Assets/ThirdParty/VRM/VRM/UniHumanoid/Scripts/IO/BvhImporterContext.cs b/Assets/ThirdParty/VRM/VRM/UniHumanoid/Scripts/IO/BvhImporterContext.cs
new file mode 100644
index 00000000..f7acb3a1
--- /dev/null
+++ b/Assets/ThirdParty/VRM/VRM/UniHumanoid/Scripts/IO/BvhImporterContext.cs
@@ -0,0 +1,235 @@
+using System;
+using System.Linq;
+using System.Collections.Generic;
+using UnityEngine;
+using System.IO;
+using System.Text;
+#if UNITY_EDITOR
+using UnityEditor;
+#endif
+
+
+namespace UniHumanoid
+{
+ [Obsolete("use BvhImporterContext")]
+ public class ImporterContext: BvhImporterContext
+ {
+ }
+
+ public class BvhImporterContext
+ {
+ #region Source
+ String m_path;
+ public String Path
+ {
+ get { return m_path; }
+ set
+ {
+ if (m_path == value) return;
+ m_path = value;
+ }
+ }
+ public String Source; // source
+ public Bvh Bvh;
+ #endregion
+
+ #region Imported
+ public GameObject Root;
+ public List<Transform> Nodes = new List<Transform>();
+ public AnimationClip Animation;
+ public AvatarDescription AvatarDescription;
+ public Avatar Avatar;
+ public Mesh Mesh;
+ public Material Material;
+ #endregion
+
+ #region Load
+ [Obsolete("use Load(path)")]
+ public void Parse()
+ {
+ Parse(Path);
+ }
+
+ public void Parse(string path)
+ {
+ Path = path;
+ Source = File.ReadAllText(Path, Encoding.UTF8);
+ Bvh = Bvh.Parse(Source);
+ }
+
+ public void Load()
+ {
+ //
+ // build hierarchy
+ //
+ Root = new GameObject(System.IO.Path.GetFileNameWithoutExtension(Path));
+ var hips = BuildHierarchy(Root.transform, Bvh.Root, 1.0f);
+ var skeleton = Skeleton.Estimate(hips);
+ var description = AvatarDescription.Create(hips.Traverse().ToArray(), skeleton);
+
+ //
+ // scaling. reposition
+ //
+ float scaling = 1.0f;
+ {
+ //var foot = animator.GetBoneTransform(HumanBodyBones.LeftFoot);
+ var foot = hips.Traverse().Skip(skeleton.GetBoneIndex(HumanBodyBones.LeftFoot)).First();
+ var hipHeight = hips.position.y - foot.position.y;
+ // hips height to a meter
+ scaling = 1.0f / hipHeight;
+ foreach (var x in Root.transform.Traverse())
+ {
+ x.localPosition *= scaling;
+ }
+
+ var scaledHeight = hipHeight * scaling;
+ hips.position = new Vector3(0, scaledHeight, 0); // foot to ground
+ }
+
+ //
+ // avatar
+ //
+ Avatar = description.CreateAvatar(Root.transform);
+ Avatar.name = "Avatar";
+ AvatarDescription = description;
+ var animator = Root.AddComponent<Animator>();
+ animator.avatar = Avatar;
+
+ //
+ // create AnimationClip
+ //
+ Animation = BvhAnimation.CreateAnimationClip(Bvh, scaling);
+ Animation.name = Root.name;
+ Animation.legacy = true;
+ Animation.wrapMode = WrapMode.Loop;
+
+ var animation = Root.AddComponent<Animation>();
+ animation.AddClip(Animation, Animation.name);
+ animation.clip = Animation;
+ animation.Play();
+
+ var humanPoseTransfer = Root.AddComponent<HumanPoseTransfer>();
+ humanPoseTransfer.Avatar = Avatar;
+
+ // create SkinnedMesh for bone visualize
+ var renderer = SkeletonMeshUtility.CreateRenderer(animator);
+ Material = new Material(Shader.Find("Standard"));
+ renderer.sharedMaterial = Material;
+ Mesh = renderer.sharedMesh;
+ Mesh.name = "box-man";
+ }
+
+ static Transform BuildHierarchy(Transform parent, BvhNode node, float toMeter)
+ {
+ var go = new GameObject(node.Name);
+ go.transform.localPosition = node.Offset.ToXReversedVector3() * toMeter;
+ go.transform.SetParent(parent, false);
+
+ //var gizmo = go.AddComponent<BoneGizmoDrawer>();
+ //gizmo.Draw = true;
+
+ foreach (var child in node.Children)
+ {
+ BuildHierarchy(go.transform, child, toMeter);
+ }
+
+ return go.transform;
+ }
+ #endregion
+
+#if UNITY_EDITOR
+ protected virtual string GetPrefabPath()
+ {
+ var dir = System.IO.Path.GetDirectoryName(Path);
+ var name = System.IO.Path.GetFileNameWithoutExtension(Path);
+ var prefabPath = string.Format("{0}/{1}.prefab", dir, name);
+ if (!Application.isPlaying && File.Exists(prefabPath))
+ {
+ // already exists
+ if (IsOwn(prefabPath))
+ {
+ //Debug.LogFormat("already exist. own: {0}", prefabPath);
+ }
+ else
+ {
+ // but unknown prefab
+ var unique = AssetDatabase.GenerateUniqueAssetPath(prefabPath);
+ //Debug.LogFormat("already exist: {0} => {1}", prefabPath, unique);
+ prefabPath = unique;
+ }
+ }
+ return prefabPath;
+ }
+
+ #region Assets
+ IEnumerable<UnityEngine.Object> GetSubAssets(string path)
+ {
+ return AssetDatabase.LoadAllAssetsAtPath(path);
+ }
+
+ protected virtual bool IsOwn(string path)
+ {
+ foreach (var x in GetSubAssets(path))
+ {
+ //if (x is Transform) continue;
+ if (x is GameObject) continue;
+ if (x is Component) continue;
+ if (AssetDatabase.IsSubAsset(x))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ IEnumerable<UnityEngine.Object> ObjectsForSubAsset()
+ {
+ if (Animation != null) yield return Animation;
+ if (AvatarDescription != null) yield return AvatarDescription;
+ if (Avatar != null) yield return Avatar;
+ if (Mesh != null) yield return Mesh;
+ if (Material != null) yield return Material;
+ }
+
+ public void SaveAsAsset()
+ {
+ var path = GetPrefabPath();
+ if (File.Exists(path))
+ {
+ // clear SubAssets
+ foreach (var x in GetSubAssets(path).Where(x => !(x is GameObject) && !(x is Component)))
+ {
+ GameObject.DestroyImmediate(x, true);
+ }
+ }
+
+ // Add SubAsset
+ foreach (var o in ObjectsForSubAsset())
+ {
+ AssetDatabase.AddObjectToAsset(o, path);
+ }
+
+ // Create or update Main Asset
+ Debug.LogFormat("create prefab: {0}", path);
+ PrefabUtility.SaveAsPrefabAssetAndConnect(Root, path, InteractionMode.AutomatedAction);
+
+ AssetDatabase.ImportAsset(path);
+ }
+ #endregion
+#endif
+
+ public void Destroy(bool destroySubAssets)
+ {
+ if (Root != null) GameObject.DestroyImmediate(Root);
+ if (destroySubAssets)
+ {
+#if UNITY_EDITOR
+ foreach (var o in ObjectsForSubAsset())
+ {
+ UnityEngine.Object.DestroyImmediate(o, true);
+ }
+#endif
+ }
+ }
+ }
+}