Merge pull request #2000 from ousttrue/feature/experimental_vrm_animation

[experimental][vrm-animation] vrm animation の試験実装
This commit is contained in:
ousttrue
2023-03-06 18:43:59 +09:00
committed by GitHub
16 changed files with 6096 additions and 209 deletions

View File

@@ -75,6 +75,57 @@ namespace UniHumanoid
}
}
class UniqueName
{
HashSet<string> m_uniqueNameSet = new HashSet<string>();
int m_counter = 1;
public void ForceUniqueName(Transform t)
{
if (!m_uniqueNameSet.Contains(t.name))
{
m_uniqueNameSet.Add(t.name);
return;
}
if (t.parent != null && t.childCount == 0)
{
/// AvatarBuilder:BuildHumanAvatar で同名の Transform があるとエラーになる。
///
/// AvatarBuilder 'GLTF': Ambiguous Transform '32/root/torso_1/torso_2/torso_3/torso_4/torso_5/torso_6/torso_7/neck_1/neck_2/head/ENDSITE' and '32/root/torso_1/torso_2/torso_3/torso_4/torso_5/torso_6/torso_7/l_shoulder/l_up_arm/l_low_arm/l_hand/ENDSITE' found in hierarchy for human bone 'Head'. Transform name mapped to a human bone must be unique.
/// UnityEngine.AvatarBuilder:BuildHumanAvatar (UnityEngine.GameObject,UnityEngine.HumanDescription)
/// UniHumanoid.AvatarDescription:CreateAvatar (UnityEngine.Transform)
///
/// 主に BVH の EndSite 由来の GameObject 名が重複することへの対策
/// ex: parent-ENDSITE
var newName = $"{t.parent.name}-{t.name}";
if (!m_uniqueNameSet.Contains(newName))
{
Debug.LogWarning($"force rename: {t.name} => {newName}");
t.name = newName;
m_uniqueNameSet.Add(newName);
return;
}
}
// 連番
for (int i = 0; i < 100; ++i)
{
// ex: name.1
var newName = $"{t.name}{m_counter++}";
if (!m_uniqueNameSet.Contains(newName))
{
Debug.LogWarning($"force rename: {t.name} => {newName}");
t.name = newName;
m_uniqueNameSet.Add(newName);
return;
}
}
throw new NotImplementedException();
}
}
[Serializable]
public class AvatarDescription : ScriptableObject
{
@@ -125,6 +176,14 @@ namespace UniHumanoid
public Avatar CreateAvatar(Transform root)
{
// force unique name
var uniqueName = new UniqueName();
var transforms = root.GetComponentsInChildren<Transform>();
foreach (var t in transforms)
{
uniqueName.ForceUniqueName(t);
}
return AvatarBuilder.BuildHumanAvatar(root.gameObject, ToHumanDescription(root));
}

View File

@@ -95,15 +95,6 @@ namespace UniHumanoid
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
//
@@ -117,15 +108,14 @@ namespace UniHumanoid
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";
//
// avatar
//
Avatar = description.CreateAvatar(Root.transform);
Avatar.name = "Avatar";
AvatarDescription = description;
var animator = Root.AddComponent<Animator>();
animator.avatar = Avatar;
}
static Transform BuildHierarchy(Transform parent, BvhNode node, float toMeter)

View File

@@ -8,75 +8,89 @@ namespace UniHumanoid
{
public static class SkeletonMeshUtility
{
readonly struct TSRBox
{
public readonly Vector3 T;
public readonly Vector3 S;
public readonly Quaternion R;
public readonly Vector3 HeadPosition;
public TSRBox(
Vector3 t,
Vector3 s,
Quaternion r,
Vector3 head)
{
T = t;
S = s;
R = r;
HeadPosition = head;
}
public Matrix4x4 ToMatrix()
{
return Matrix4x4.Translate(HeadPosition)
* Matrix4x4.Rotate(R) * Matrix4x4.Scale(S) * Matrix4x4.Translate(T);
}
}
class MeshBuilder
{
List<Vector3> m_positions = new List<Vector3>();
List<int> m_indices = new List<int>();
List<BoneWeight> m_boneWeights = new List<BoneWeight>();
public void AddBone(Vector3 head, Vector3 tail, int boneIndex, float xWidth, float zWidth)
public void AddBone(Vector3 head, Vector3 tail, int boneIndex, float width, float height, Vector3 xAxis)
{
var dir = (tail - head).normalized;
Vector3 xaxis;
Vector3 zaxis;
if (Vector3.Dot(dir, Vector3.forward) >= 1.0f - float.Epsilon)
{
xaxis = Vector3.right;
zaxis = Vector3.down;
}
else
{
xaxis = Vector3.Cross(dir, Vector3.forward).normalized;
zaxis = Vector3.forward;
}
AddBox((head+tail)*0.5f,
xaxis*xWidth,
(tail-head)*0.5f,
zaxis*zWidth,
boneIndex);
var yAxis = (tail - head).normalized;
var zAxis = Vector3.Cross(xAxis, yAxis);
xAxis = Vector3.Cross(yAxis, zAxis);
AddBox(boneIndex, new TSRBox
(
new Vector3(0, 0.5f, 0),
new Vector3(width, (tail - head).magnitude, height),
new Matrix4x4(
xAxis, yAxis, zAxis, new Vector4(0, 0, 0, 1)
).rotation,
head
));
}
void AddBox(Vector3 center, Vector3 xaxis, Vector3 yaxis, Vector3 zaxis, int boneIndex)
// rotation * scale * beforeTranslation
void AddBox(int boneIndex, TSRBox box)
{
AddQuad(
center - yaxis - xaxis - zaxis,
center - yaxis + xaxis - zaxis,
center - yaxis + xaxis + zaxis,
center - yaxis - xaxis + zaxis,
boneIndex);
AddQuad(
center + yaxis - xaxis - zaxis,
center + yaxis + xaxis - zaxis,
center + yaxis + xaxis + zaxis,
center + yaxis - xaxis + zaxis,
boneIndex, true);
AddQuad(
center - xaxis - yaxis - zaxis,
center - xaxis + yaxis - zaxis,
center - xaxis + yaxis + zaxis,
center - xaxis - yaxis + zaxis,
boneIndex, true);
AddQuad(
center + xaxis - yaxis - zaxis,
center + xaxis + yaxis - zaxis,
center + xaxis + yaxis + zaxis,
center + xaxis - yaxis + zaxis,
boneIndex);
AddQuad(
center - zaxis - xaxis - yaxis,
center - zaxis + xaxis - yaxis,
center - zaxis + xaxis + yaxis,
center - zaxis - xaxis + yaxis,
boneIndex, true);
AddQuad(
center + zaxis - xaxis - yaxis,
center + zaxis + xaxis - yaxis,
center + zaxis + xaxis + yaxis,
center + zaxis - xaxis + yaxis,
boneIndex);
var m = box.ToMatrix();
// v6+---+v7
// v2/| v3|
// +---+ |
// | +v5-+v4
// |/ |/
// +---+
// v1 v0
var s = 0.5f;
var cube = new Vector3[]
{
m.MultiplyPoint(new Vector3(+s, -s, -s)),
m.MultiplyPoint(new Vector3(-s, -s, -s)),
m.MultiplyPoint(new Vector3(-s, +s, -s)),
m.MultiplyPoint(new Vector3(+s, +s, -s)),
m.MultiplyPoint(new Vector3(+s, -s, +s)),
m.MultiplyPoint(new Vector3(-s, -s, +s)),
m.MultiplyPoint(new Vector3(-s, +s, +s)),
m.MultiplyPoint(new Vector3(+s, +s, +s)),
};
AddQuad(boneIndex, cube[0], cube[1], cube[2], cube[3]);
AddQuad(boneIndex, cube[1], cube[5], cube[6], cube[2]);
AddQuad(boneIndex, cube[5], cube[4], cube[7], cube[6]);
AddQuad(boneIndex, cube[4], cube[0], cube[3], cube[7]);
AddQuad(boneIndex, cube[3], cube[2], cube[6], cube[7]);
AddQuad(boneIndex, cube[4], cube[5], cube[1], cube[0]);
}
void AddQuad(Vector3 v0, Vector3 v1, Vector3 v2, Vector3 v3, int boneIndex, bool reverse=false)
void AddQuad(int boneIndex, Vector3 v0, Vector3 v1, Vector3 v2, Vector3 v3)
{
var i = m_positions.Count;
m_positions.Add(v0);
@@ -86,25 +100,14 @@ namespace UniHumanoid
var bw = new BoneWeight
{
boneIndex0=boneIndex,
weight0=1.0f,
boneIndex0 = boneIndex,
weight0 = 1.0f,
};
m_boneWeights.Add(bw);
m_boneWeights.Add(bw);
m_boneWeights.Add(bw);
m_boneWeights.Add(bw);
if (reverse)
{
m_indices.Add(i + 3);
m_indices.Add(i + 2);
m_indices.Add(i + 1);
m_indices.Add(i + 1);
m_indices.Add(i);
m_indices.Add(i + 3);
}
else
{
m_indices.Add(i);
m_indices.Add(i + 1);
@@ -133,55 +136,59 @@ namespace UniHumanoid
public HumanBodyBones Head;
public HumanBodyBones Tail;
public Vector3 TailOffset;
public float XWidth;
public float ZWidth;
public float Width;
public float Height;
public Vector3 XAxis;
public BoneHeadTail(HumanBodyBones head, HumanBodyBones tail, float xWidth = 0.05f, float zWidth = 0.05f)
public BoneHeadTail(HumanBodyBones head, HumanBodyBones tail, Vector3 xAxis, float width = 0.05f, float height = 0.05f)
{
Head = head;
Tail = tail;
TailOffset = Vector3.zero;
XWidth = xWidth;
ZWidth = zWidth;
XAxis = xAxis;
Width = width;
Height = height;
}
public BoneHeadTail(HumanBodyBones head, Vector3 tailOffset, float xWidth = 0.05f, float zWidth = 0.05f)
public BoneHeadTail(HumanBodyBones head, Vector3 tailOffset, Vector3 xAxis, float width = 0.05f, float height = 0.05f)
{
Head = head;
Tail = HumanBodyBones.LastBone;
TailOffset = tailOffset;
XWidth = xWidth;
ZWidth = zWidth;
XAxis = xAxis;
Width = width;
Height = height;
}
}
static BoneHeadTail[] Bones = new BoneHeadTail[]
{
new BoneHeadTail(HumanBodyBones.Hips, HumanBodyBones.Spine, 0.1f, 0.06f),
new BoneHeadTail(HumanBodyBones.Spine, HumanBodyBones.Chest),
new BoneHeadTail(HumanBodyBones.Chest, HumanBodyBones.Neck, 0.1f, 0.06f),
new BoneHeadTail(HumanBodyBones.Neck, HumanBodyBones.Head, 0.03f, 0.03f),
new BoneHeadTail(HumanBodyBones.Head, new Vector3(0, 0.1f, 0), 0.1f, 0.1f),
new BoneHeadTail(HumanBodyBones.Hips, HumanBodyBones.Spine, Vector3.right, 0.2f, 0.12f),
new BoneHeadTail(HumanBodyBones.Spine, HumanBodyBones.Chest, Vector3.right),
new BoneHeadTail(HumanBodyBones.Chest, HumanBodyBones.Neck, Vector3.right, 0.2f, 0.12f),
new BoneHeadTail(HumanBodyBones.Neck, HumanBodyBones.Head, Vector3.right, 0.06f, 0.06f),
new BoneHeadTail(HumanBodyBones.Head, new Vector3(0, 0.1f, 0), Vector3.right, 0.2f, 0.2f),
new BoneHeadTail(HumanBodyBones.Head, new Vector3(0, 0, 0.1f), Vector3.right, 0.2f, 0.2f),
new BoneHeadTail(HumanBodyBones.LeftShoulder, HumanBodyBones.LeftUpperArm),
new BoneHeadTail(HumanBodyBones.LeftUpperArm, HumanBodyBones.LeftLowerArm),
new BoneHeadTail(HumanBodyBones.LeftLowerArm, HumanBodyBones.LeftHand),
new BoneHeadTail(HumanBodyBones.LeftHand, new Vector3(-0.1f, 0, 0)),
new BoneHeadTail(HumanBodyBones.LeftShoulder, HumanBodyBones.LeftUpperArm, Vector3.forward),
new BoneHeadTail(HumanBodyBones.LeftUpperArm, HumanBodyBones.LeftLowerArm, Vector3.forward),
new BoneHeadTail(HumanBodyBones.LeftLowerArm, HumanBodyBones.LeftHand, Vector3.forward),
new BoneHeadTail(HumanBodyBones.LeftHand, new Vector3(-0.1f, 0, 0), Vector3.forward, 0.1f, 0.02f),
new BoneHeadTail(HumanBodyBones.LeftUpperLeg, HumanBodyBones.LeftLowerLeg),
new BoneHeadTail(HumanBodyBones.LeftLowerLeg, HumanBodyBones.LeftFoot),
new BoneHeadTail(HumanBodyBones.LeftFoot, HumanBodyBones.LeftToes),
new BoneHeadTail(HumanBodyBones.LeftToes, new Vector3(0, 0, 0.1f)),
new BoneHeadTail(HumanBodyBones.LeftUpperLeg, HumanBodyBones.LeftLowerLeg, Vector3.left),
new BoneHeadTail(HumanBodyBones.LeftLowerLeg, HumanBodyBones.LeftFoot, Vector3.left),
new BoneHeadTail(HumanBodyBones.LeftFoot, HumanBodyBones.LeftToes, Vector3.left),
new BoneHeadTail(HumanBodyBones.LeftToes, new Vector3(0, 0, 0.03f), Vector3.left),
new BoneHeadTail(HumanBodyBones.RightShoulder, HumanBodyBones.RightUpperArm),
new BoneHeadTail(HumanBodyBones.RightUpperArm, HumanBodyBones.RightLowerArm),
new BoneHeadTail(HumanBodyBones.RightLowerArm, HumanBodyBones.RightHand),
new BoneHeadTail(HumanBodyBones.RightHand, new Vector3(0.1f, 0, 0)),
new BoneHeadTail(HumanBodyBones.RightShoulder, HumanBodyBones.RightUpperArm, Vector3.back),
new BoneHeadTail(HumanBodyBones.RightUpperArm, HumanBodyBones.RightLowerArm, Vector3.back),
new BoneHeadTail(HumanBodyBones.RightLowerArm, HumanBodyBones.RightHand, Vector3.back),
new BoneHeadTail(HumanBodyBones.RightHand, new Vector3(0.1f, 0, 0), Vector3.back, 0.1f, 0.02f),
new BoneHeadTail(HumanBodyBones.RightUpperLeg, HumanBodyBones.RightLowerLeg),
new BoneHeadTail(HumanBodyBones.RightLowerLeg, HumanBodyBones.RightFoot),
new BoneHeadTail(HumanBodyBones.RightFoot, HumanBodyBones.RightToes),
new BoneHeadTail(HumanBodyBones.RightToes, new Vector3(0, 0, 0.1f)),
new BoneHeadTail(HumanBodyBones.RightUpperLeg, HumanBodyBones.RightLowerLeg, Vector3.left),
new BoneHeadTail(HumanBodyBones.RightLowerLeg, HumanBodyBones.RightFoot, Vector3.left),
new BoneHeadTail(HumanBodyBones.RightFoot, HumanBodyBones.RightToes, Vector3.left),
new BoneHeadTail(HumanBodyBones.RightToes, new Vector3(0, 0, 0.03f), Vector3.left),
};
public static SkinnedMeshRenderer CreateRenderer(Animator animator)
@@ -189,24 +196,24 @@ namespace UniHumanoid
var bones = animator.transform.Traverse().ToList();
var builder = new MeshBuilder();
foreach(var headTail in Bones)
foreach (var headTail in Bones)
{
var head = animator.GetBoneTransform(headTail.Head);
if (head!=null)
if (head != null)
{
Transform tail = null;
if(headTail.Tail!= HumanBodyBones.LastBone)
if (headTail.Tail != HumanBodyBones.LastBone)
{
tail = animator.GetBoneTransform(headTail.Tail);
}
if (tail != null)
{
builder.AddBone(head.position, tail.position, bones.IndexOf(head), headTail.XWidth, headTail.ZWidth);
builder.AddBone(head.position, tail.position, bones.IndexOf(head), headTail.Width, headTail.Height, headTail.XAxis);
}
else
{
builder.AddBone(head.position, head.position + headTail.TailOffset, bones.IndexOf(head), headTail.XWidth, headTail.ZWidth);
builder.AddBone(head.position, head.position + headTail.TailOffset, bones.IndexOf(head), headTail.Width, headTail.Height, headTail.XAxis);
}
}
else
@@ -217,8 +224,8 @@ namespace UniHumanoid
var mesh = builder.CreateMesh();
mesh.name = "box-man";
mesh.bindposes = bones.Select(x =>
x.worldToLocalMatrix * animator.transform.localToWorldMatrix).ToArray();
mesh.bindposes = bones.Select(x => x.worldToLocalMatrix * animator.transform.localToWorldMatrix).ToArray();
var renderer = animator.gameObject.AddComponent<SkinnedMeshRenderer>();
renderer.bones = bones.ToArray();
renderer.rootBone = animator.GetBoneTransform(HumanBodyBones.Hips);

View File

@@ -73,6 +73,12 @@ namespace UniVRM10
$"{SPEC_DIR}/VRMC_node_constraint-1.0/schema/VRMC_node_constraint.schema.json",
"Assets/VRM10/Runtime/Format/Constraints"
),
// VRMC_animation
new GenerateInfo(
$"{SPEC_DIR}/VRMC_vrm_animation-1.0/schema/VRMC_vrm_animation.schema.json",
"Assets/VRM10/Runtime/Format/Animation"
),
};
foreach (var arg in args)

View File

@@ -19,17 +19,19 @@ namespace UniVRM10
Transform m_root;
Transform m_hips;
private readonly Dictionary<HumanBodyBones, BoneInitialRotation> m_bones = new Dictionary<HumanBodyBones, BoneInitialRotation>();
private readonly Dictionary<HumanBodyBones, EuclideanTransform> m_worldMap = new Dictionary<HumanBodyBones, EuclideanTransform>();
public Vector3 HipTPoseWorldPosition => throw new System.NotImplementedException();
public InitRotationPoseProvider(Transform root, UniHumanoid.Humanoid humanoid)
{
m_root = root;
m_hips = m_bones[HumanBodyBones.Hips].Transform;
foreach (var (t, bone) in humanoid.BoneMap)
{
m_bones.Add(bone, new BoneInitialRotation(t));
m_worldMap.Add(bone, new EuclideanTransform(root.localToWorldMatrix * t.localToWorldMatrix));
}
m_hips = m_bones[HumanBodyBones.Hips].Transform;
}
Quaternion INormalizedPoseProvider.GetNormalizedLocalRotation(HumanBodyBones bone, HumanBodyBones parentBone)
@@ -53,13 +55,20 @@ namespace UniVRM10
}
else
{
throw new System.NotImplementedException();
return m_root.worldToLocalMatrix.MultiplyPoint(m_hips.position);
}
}
EuclideanTransform? ITPoseProvider.GetWorldTransform(HumanBodyBones bone)
{
throw new System.NotImplementedException();
if (m_worldMap.TryGetValue(bone, out var t))
{
return t;
}
else
{
return default;
}
}
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 8d15d1d42c630e94faaf48208777a17a
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4496eacf38a3897479cfb145617739ac
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,319 @@
// This file is generated from JsonSchema. Don't modify this source code.
using System;
using System.Collections.Generic;
namespace UniGLTF.Extensions.VRMC_vrm_animation
{
public class HumanBone
{
// Dictionary object with extension-specific objects.
public object Extensions;
// Application-specific data.
public object Extras;
// Represents a single glTF node mapped to this humanBone.
public int? Node;
}
public class HumanBones
{
// Dictionary object with extension-specific objects.
public object Extensions;
// Application-specific data.
public object Extras;
// Represents a single bone of a Humanoid.
public HumanBone Hips;
// Represents a single bone of a Humanoid.
public HumanBone Spine;
// Represents a single bone of a Humanoid.
public HumanBone Chest;
// Represents a single bone of a Humanoid.
public HumanBone UpperChest;
// Represents a single bone of a Humanoid.
public HumanBone Neck;
// Represents a single bone of a Humanoid.
public HumanBone Head;
// Represents a single bone of a Humanoid.
public HumanBone Jaw;
// Represents a single bone of a Humanoid.
public HumanBone LeftUpperLeg;
// Represents a single bone of a Humanoid.
public HumanBone LeftLowerLeg;
// Represents a single bone of a Humanoid.
public HumanBone LeftFoot;
// Represents a single bone of a Humanoid.
public HumanBone LeftToes;
// Represents a single bone of a Humanoid.
public HumanBone RightUpperLeg;
// Represents a single bone of a Humanoid.
public HumanBone RightLowerLeg;
// Represents a single bone of a Humanoid.
public HumanBone RightFoot;
// Represents a single bone of a Humanoid.
public HumanBone RightToes;
// Represents a single bone of a Humanoid.
public HumanBone LeftShoulder;
// Represents a single bone of a Humanoid.
public HumanBone LeftUpperArm;
// Represents a single bone of a Humanoid.
public HumanBone LeftLowerArm;
// Represents a single bone of a Humanoid.
public HumanBone LeftHand;
// Represents a single bone of a Humanoid.
public HumanBone RightShoulder;
// Represents a single bone of a Humanoid.
public HumanBone RightUpperArm;
// Represents a single bone of a Humanoid.
public HumanBone RightLowerArm;
// Represents a single bone of a Humanoid.
public HumanBone RightHand;
// Represents a single bone of a Humanoid.
public HumanBone LeftThumbMetacarpal;
// Represents a single bone of a Humanoid.
public HumanBone LeftThumbProximal;
// Represents a single bone of a Humanoid.
public HumanBone LeftThumbDistal;
// Represents a single bone of a Humanoid.
public HumanBone LeftIndexProximal;
// Represents a single bone of a Humanoid.
public HumanBone LeftIndexIntermediate;
// Represents a single bone of a Humanoid.
public HumanBone LeftIndexDistal;
// Represents a single bone of a Humanoid.
public HumanBone LeftMiddleProximal;
// Represents a single bone of a Humanoid.
public HumanBone LeftMiddleIntermediate;
// Represents a single bone of a Humanoid.
public HumanBone LeftMiddleDistal;
// Represents a single bone of a Humanoid.
public HumanBone LeftRingProximal;
// Represents a single bone of a Humanoid.
public HumanBone LeftRingIntermediate;
// Represents a single bone of a Humanoid.
public HumanBone LeftRingDistal;
// Represents a single bone of a Humanoid.
public HumanBone LeftLittleProximal;
// Represents a single bone of a Humanoid.
public HumanBone LeftLittleIntermediate;
// Represents a single bone of a Humanoid.
public HumanBone LeftLittleDistal;
// Represents a single bone of a Humanoid.
public HumanBone RightThumbMetacarpal;
// Represents a single bone of a Humanoid.
public HumanBone RightThumbProximal;
// Represents a single bone of a Humanoid.
public HumanBone RightThumbDistal;
// Represents a single bone of a Humanoid.
public HumanBone RightIndexProximal;
// Represents a single bone of a Humanoid.
public HumanBone RightIndexIntermediate;
// Represents a single bone of a Humanoid.
public HumanBone RightIndexDistal;
// Represents a single bone of a Humanoid.
public HumanBone RightMiddleProximal;
// Represents a single bone of a Humanoid.
public HumanBone RightMiddleIntermediate;
// Represents a single bone of a Humanoid.
public HumanBone RightMiddleDistal;
// Represents a single bone of a Humanoid.
public HumanBone RightRingProximal;
// Represents a single bone of a Humanoid.
public HumanBone RightRingIntermediate;
// Represents a single bone of a Humanoid.
public HumanBone RightRingDistal;
// Represents a single bone of a Humanoid.
public HumanBone RightLittleProximal;
// Represents a single bone of a Humanoid.
public HumanBone RightLittleIntermediate;
// Represents a single bone of a Humanoid.
public HumanBone RightLittleDistal;
}
public class Humanoid
{
// Dictionary object with extension-specific objects.
public object Extensions;
// Application-specific data.
public object Extras;
// An object which maps humanoid bones to nodes.
public HumanBones HumanBones;
}
public class Expression
{
// Dictionary object with extension-specific objects.
public object Extensions;
// Application-specific data.
public object Extras;
// Represents a single glTF node mapped to this expression.
public int? Node;
}
public class Preset
{
// Represents a single expression.
public Expression Happy;
// Represents a single expression.
public Expression Angry;
// Represents a single expression.
public Expression Sad;
// Represents a single expression.
public Expression Relaxed;
// Represents a single expression.
public Expression Surprised;
// Represents a single expression.
public Expression Aa;
// Represents a single expression.
public Expression Ih;
// Represents a single expression.
public Expression Ou;
// Represents a single expression.
public Expression Ee;
// Represents a single expression.
public Expression Oh;
// Represents a single expression.
public Expression Blink;
// Represents a single expression.
public Expression BlinkLeft;
// Represents a single expression.
public Expression BlinkRight;
// Represents a single expression.
public Expression LookUp;
// Represents a single expression.
public Expression LookDown;
// Represents a single expression.
public Expression LookLeft;
// Represents a single expression.
public Expression LookRight;
// Represents a single expression.
public Expression Neutral;
}
public class Expressions
{
// Dictionary object with extension-specific objects.
public object Extensions;
// Application-specific data.
public object Extras;
// An object that contains definitions of preset expressions.
public Preset Preset;
// An object that contains definitions of custom expressions.
public Dictionary<string, Expression> Custom;
}
public class LookAt
{
// Dictionary object with extension-specific objects.
public object Extensions;
// Application-specific data.
public object Extras;
// Represents a single glTF node represents the eye gaze point.
public int? Node;
}
public class VRMC_vrm_animation
{
public const string ExtensionName = "VRMC_vrm_animation";
// Dictionary object with extension-specific objects.
public object Extensions;
// Application-specific data.
public object Extras;
// Specification version of VRMC_vrm_animation
public string SpecVersion;
// An object which describes about humanoid bones.
public Humanoid Humanoid;
// An object which maps expressions to nodes.
public Expressions Expressions;
// An object which maps a eye gaze point to a node.
public LookAt LookAt;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f595db5658d457449b2fa63cfdc29c6d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b1cc771337f6bbf4b932505a7847455a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -11,62 +11,217 @@ using VRMShaders;
namespace UniVRM10.VRM10Viewer
{
public class VRM10Motion
public interface IMotion : IDisposable
{
public (INormalizedPoseProvider, ITPoseProvider) ControlRig;
(INormalizedPoseProvider, ITPoseProvider) ControlRig { get; }
void ShowBoxMan(bool enable);
}
public class BvhMotion : IMotion
{
UniHumanoid.BvhImporterContext m_context;
UniGLTF.RuntimeGltfInstance m_instance;
public Transform Root => m_context?.Root.transform;
public VRM10Motion(UniHumanoid.BvhImporterContext context)
public SkinnedMeshRenderer m_boxMan;
public SkinnedMeshRenderer BoxMan => m_boxMan;
(INormalizedPoseProvider, ITPoseProvider) m_controlRig;
(INormalizedPoseProvider, ITPoseProvider) IMotion.ControlRig => m_controlRig;
public BvhMotion(UniHumanoid.BvhImporterContext context)
{
m_context = context;
var provider = new AnimatorPoseProvider(m_context.Root.transform, m_context.Root.GetComponent<Animator>());
ControlRig = (provider, provider);
m_controlRig = (provider, provider);
// create SkinnedMesh for bone visualize
var animator = m_context.Root.GetComponent<Animator>();
m_boxMan = SkeletonMeshUtility.CreateRenderer(animator);
var material = new Material(Shader.Find("Standard"));
BoxMan.sharedMaterial = material;
var mesh = BoxMan.sharedMesh;
mesh.name = "box-man";
}
public VRM10Motion(UniGLTF.RuntimeGltfInstance instance)
public static BvhMotion LoadBvhFromText(string source, string path = "tmp.bvh")
{
var context = new UniHumanoid.BvhImporterContext();
context.Parse(path, source);
context.Load();
return new BvhMotion(context);
}
public static BvhMotion LoadBvhFromPath(string path)
{
return LoadBvhFromText(File.ReadAllText(path), path);
}
public void ShowBoxMan(bool enable)
{
m_boxMan.enabled = enable;
}
public void Dispose()
{
GameObject.Destroy(m_context.Root);
}
}
public class VrmAnimation : IMotion
{
UniGLTF.RuntimeGltfInstance m_instance;
public SkinnedMeshRenderer m_boxMan;
public SkinnedMeshRenderer BoxMan => m_boxMan;
(INormalizedPoseProvider, ITPoseProvider) m_controlRig;
(INormalizedPoseProvider, ITPoseProvider) IMotion.ControlRig => m_controlRig;
public VrmAnimation(UniGLTF.RuntimeGltfInstance instance)
{
m_instance = instance;
if (instance.GetComponent<Animation>() is Animation animation)
{
animation.Play();
}
var humanoid = instance.gameObject.AddComponent<Humanoid>();
humanoid.AssignBonesFromAnimator();
var provider = new InitRotationPoseProvider(instance.transform, humanoid);
m_controlRig = (provider, provider);
// create SkinnedMesh for bone visualize
var animator = instance.GetComponent<Animator>();
m_boxMan = SkeletonMeshUtility.CreateRenderer(animator);
var material = new Material(Shader.Find("Standard"));
BoxMan.sharedMaterial = material;
var mesh = BoxMan.sharedMesh;
mesh.name = "box-man";
}
public void ShowBoxMan(bool showBoxMan)
public void ShowBoxMan(bool enable)
{
if (m_context != null)
m_boxMan.enabled = enable;
}
public void Dispose()
{
GameObject.Destroy(m_boxMan.gameObject);
}
static int? GetNodeIndex(UniGLTF.Extensions.VRMC_vrm_animation.Humanoid humanoid, HumanBodyBones bone)
{
switch (bone)
{
m_context.Root.GetComponent<SkinnedMeshRenderer>().enabled = showBoxMan;
case HumanBodyBones.Hips: return humanoid.HumanBones.Hips?.Node;
case HumanBodyBones.LeftUpperLeg: return humanoid.HumanBones.LeftUpperLeg?.Node;
case HumanBodyBones.RightUpperLeg: return humanoid.HumanBones.RightUpperLeg?.Node;
case HumanBodyBones.LeftLowerLeg: return humanoid.HumanBones.LeftLowerLeg?.Node;
case HumanBodyBones.RightLowerLeg: return humanoid.HumanBones.RightLowerLeg?.Node;
case HumanBodyBones.LeftFoot: return humanoid.HumanBones.LeftFoot?.Node;
case HumanBodyBones.RightFoot: return humanoid.HumanBones.RightFoot?.Node;
case HumanBodyBones.Spine: return humanoid.HumanBones.Spine?.Node;
case HumanBodyBones.Chest: return humanoid.HumanBones.Chest?.Node;
case HumanBodyBones.Neck: return humanoid.HumanBones.Neck?.Node;
case HumanBodyBones.Head: return humanoid.HumanBones.Head?.Node;
case HumanBodyBones.LeftShoulder: return humanoid.HumanBones.LeftShoulder?.Node;
case HumanBodyBones.RightShoulder: return humanoid.HumanBones.RightShoulder?.Node;
case HumanBodyBones.LeftUpperArm: return humanoid.HumanBones.LeftUpperArm?.Node;
case HumanBodyBones.RightUpperArm: return humanoid.HumanBones.RightUpperArm?.Node;
case HumanBodyBones.LeftLowerArm: return humanoid.HumanBones.LeftLowerArm?.Node;
case HumanBodyBones.RightLowerArm: return humanoid.HumanBones.RightLowerArm?.Node;
case HumanBodyBones.LeftHand: return humanoid.HumanBones.LeftHand?.Node;
case HumanBodyBones.RightHand: return humanoid.HumanBones.RightHand?.Node;
case HumanBodyBones.LeftToes: return humanoid.HumanBones.LeftToes?.Node;
case HumanBodyBones.RightToes: return humanoid.HumanBones.RightToes?.Node;
// case HumanBodyBones.LeftEye: return humanoid.HumanBones.LeftEye?.Node;
// case HumanBodyBones.RightEye: return humanoid.HumanBones.RightEye?.Node;
case HumanBodyBones.Jaw: return humanoid.HumanBones.Jaw?.Node;
case HumanBodyBones.LeftThumbProximal: return humanoid.HumanBones.LeftThumbMetacarpal?.Node; // Metacarpal
case HumanBodyBones.LeftThumbIntermediate: return humanoid.HumanBones.LeftThumbProximal?.Node; // Proximal
case HumanBodyBones.LeftThumbDistal: return humanoid.HumanBones.LeftThumbDistal?.Node;
case HumanBodyBones.LeftIndexProximal: return humanoid.HumanBones.LeftIndexProximal?.Node;
case HumanBodyBones.LeftIndexIntermediate: return humanoid.HumanBones.LeftIndexIntermediate?.Node;
case HumanBodyBones.LeftIndexDistal: return humanoid.HumanBones.LeftIndexDistal?.Node;
case HumanBodyBones.LeftMiddleProximal: return humanoid.HumanBones.LeftMiddleProximal?.Node;
case HumanBodyBones.LeftMiddleIntermediate: return humanoid.HumanBones.LeftMiddleIntermediate?.Node;
case HumanBodyBones.LeftMiddleDistal: return humanoid.HumanBones.LeftMiddleDistal?.Node;
case HumanBodyBones.LeftRingProximal: return humanoid.HumanBones.LeftRingProximal?.Node;
case HumanBodyBones.LeftRingIntermediate: return humanoid.HumanBones.LeftRingIntermediate?.Node;
case HumanBodyBones.LeftRingDistal: return humanoid.HumanBones.LeftRingDistal?.Node;
case HumanBodyBones.LeftLittleProximal: return humanoid.HumanBones.LeftLittleProximal?.Node;
case HumanBodyBones.LeftLittleIntermediate: return humanoid.HumanBones.LeftLittleIntermediate?.Node;
case HumanBodyBones.LeftLittleDistal: return humanoid.HumanBones.LeftLittleDistal?.Node;
case HumanBodyBones.RightThumbProximal: return humanoid.HumanBones.RightThumbMetacarpal?.Node; // Metacarpal
case HumanBodyBones.RightThumbIntermediate: return humanoid.HumanBones.RightThumbProximal?.Node; // Proximal
case HumanBodyBones.RightThumbDistal: return humanoid.HumanBones.RightThumbDistal?.Node;
case HumanBodyBones.RightIndexProximal: return humanoid.HumanBones.RightIndexProximal?.Node;
case HumanBodyBones.RightIndexIntermediate: return humanoid.HumanBones.RightIndexIntermediate?.Node;
case HumanBodyBones.RightIndexDistal: return humanoid.HumanBones.RightIndexDistal?.Node;
case HumanBodyBones.RightMiddleProximal: return humanoid.HumanBones.RightMiddleProximal?.Node;
case HumanBodyBones.RightMiddleIntermediate: return humanoid.HumanBones.RightMiddleIntermediate?.Node;
case HumanBodyBones.RightMiddleDistal: return humanoid.HumanBones.RightMiddleDistal?.Node;
case HumanBodyBones.RightRingProximal: return humanoid.HumanBones.RightRingProximal?.Node;
case HumanBodyBones.RightRingIntermediate: return humanoid.HumanBones.RightRingIntermediate?.Node;
case HumanBodyBones.RightRingDistal: return humanoid.HumanBones.RightRingDistal?.Node;
case HumanBodyBones.RightLittleProximal: return humanoid.HumanBones.RightLittleProximal?.Node;
case HumanBodyBones.RightLittleIntermediate: return humanoid.HumanBones.RightLittleIntermediate?.Node;
case HumanBodyBones.RightLittleDistal: return humanoid.HumanBones.RightLittleDistal?.Node;
case HumanBodyBones.UpperChest: return humanoid.HumanBones.UpperChest?.Node;
}
return default;
}
public static VRM10Motion LoadBvhFromText(string source, string path = "tmp.bvh")
static Dictionary<HumanBodyBones, Transform> GetHumanMap(GltfData data, IReadOnlyList<Transform> nodes)
{
var context = new UniHumanoid.BvhImporterContext();
context.Parse(path, source);
context.Load();
return new VRM10Motion(context);
}
var humanMap = new Dictionary<HumanBodyBones, Transform>();
public static VRM10Motion LoadBvhFromPath(string path)
{
return LoadBvhFromText(File.ReadAllText(path), path);
}
static IEnumerable<Transform> Traverse(Transform t)
{
yield return t;
foreach (Transform child in t)
if (data.GLTF.extensions is UniGLTF.glTFExtensionImport extensions)
{
foreach (var x in Traverse(child))
foreach (var kv in extensions.ObjectItems())
{
yield return x;
if (kv.Key.GetString() == "VRMC_vrm_animation")
{
var animation = UniGLTF.Extensions.VRMC_vrm_animation.GltfDeserializer.Deserialize(kv.Value);
foreach (HumanBodyBones bone in UniGLTF.Utils.CachedEnum.GetValues<HumanBodyBones>())
{
// Debug.Log($"{bone} => {index}");
var node = GetNodeIndex(animation.Humanoid, bone);
if (node.HasValue)
{
humanMap.Add(bone, nodes[node.Value]);
}
}
}
}
}
return humanMap;
}
public static async Task<VrmAnimation> LoadVrmAnimationFromPathAsync(string path)
{
//
// GetHumanoid Mapping
//
using (GltfData data = new AutoGltfFileParser(path).Parse())
using (var loader = new UniGLTF.ImporterContext(data))
{
loader.InvertAxis = Axes.X;
// loader.PositionScaling = 0.01f;
var instance = await loader.LoadAsync(new ImmediateCaller());
var humanMap = GetHumanMap(data, loader.Nodes);
if (humanMap.Count == 0)
{
throw new ArgumentException("fail to load VRMC_vrm_animation");
}
var description = AvatarDescription.Create(humanMap);
//
// avatar
//
var avatar = description.CreateAvatar(instance.Root.transform);
avatar.name = "Avatar";
// AvatarDescription = description;
var animator = instance.gameObject.AddComponent<Animator>();
animator.avatar = avatar;
return new VrmAnimation(instance);
}
}
}
}

View File

@@ -230,7 +230,7 @@ RectTransform:
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 339774397}
m_RootOrder: 11
m_RootOrder: 13
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
@@ -394,6 +394,127 @@ CanvasRenderer:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 154330167}
m_CullTransparentMesh: 0
--- !u!1 &168425994
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 168425995}
- component: {fileID: 168425998}
- component: {fileID: 168425997}
- component: {fileID: 168425996}
m_Layer: 5
m_Name: OpenMotion
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &168425995
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 168425994}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children:
- {fileID: 1923525315}
m_Father: {fileID: 339774397}
m_RootOrder: 2
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 162, y: 30}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &168425996
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 168425994}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Navigation:
m_Mode: 3
m_WrapAround: 0
m_SelectOnUp: {fileID: 0}
m_SelectOnDown: {fileID: 0}
m_SelectOnLeft: {fileID: 0}
m_SelectOnRight: {fileID: 0}
m_Transition: 1
m_Colors:
m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
m_ColorMultiplier: 1
m_FadeDuration: 0.1
m_SpriteState:
m_HighlightedSprite: {fileID: 0}
m_PressedSprite: {fileID: 0}
m_SelectedSprite: {fileID: 0}
m_DisabledSprite: {fileID: 0}
m_AnimationTriggers:
m_NormalTrigger: Normal
m_HighlightedTrigger: Highlighted
m_PressedTrigger: Pressed
m_SelectedTrigger: Highlighted
m_DisabledTrigger: Disabled
m_Interactable: 1
m_TargetGraphic: {fileID: 168425997}
m_OnClick:
m_PersistentCalls:
m_Calls: []
--- !u!114 &168425997
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 168425994}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0}
m_Type: 1
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!222 &168425998
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 168425994}
m_CullTransparentMesh: 0
--- !u!1 &175751362
GameObject:
m_ObjectHideFlags: 0
@@ -1097,10 +1218,12 @@ RectTransform:
m_Children:
- {fileID: 1621794411}
- {fileID: 2009818432}
- {fileID: 1557052150}
- {fileID: 168425995}
- {fileID: 224350191}
- {fileID: 1791103379}
- {fileID: 1311520909}
- {fileID: 1557052150}
- {fileID: 1767706907}
- {fileID: 974864191}
- {fileID: 597950322}
- {fileID: 935566651}
@@ -1595,7 +1718,7 @@ RectTransform:
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 339774397}
m_RootOrder: 7
m_RootOrder: 9
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
@@ -1675,7 +1798,7 @@ RectTransform:
- {fileID: 154330168}
- {fileID: 1954133885}
m_Father: {fileID: 339774397}
m_RootOrder: 13
m_RootOrder: 15
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
@@ -1761,7 +1884,7 @@ RectTransform:
- {fileID: 2010083454}
- {fileID: 1081455630}
m_Father: {fileID: 339774397}
m_RootOrder: 9
m_RootOrder: 11
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
@@ -1816,6 +1939,85 @@ MonoBehaviour:
m_PersistentCalls:
m_Calls: []
m_IsOn: 1
--- !u!1 &642985707
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 642985708}
- component: {fileID: 642985710}
- component: {fileID: 642985709}
m_Layer: 5
m_Name: Label
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &642985708
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 642985707}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 1767706907}
m_RootOrder: 1
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 9, y: -0.5}
m_SizeDelta: {x: -28, y: -3}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &642985709
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 642985707}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_FontData:
m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
m_FontSize: 14
m_FontStyle: 0
m_BestFit: 0
m_MinSize: 10
m_MaxSize: 40
m_Alignment: 0
m_AlignByGeometry: 0
m_RichText: 1
m_HorizontalOverflow: 0
m_VerticalOverflow: 0
m_LineSpacing: 1
m_Text: ShowBoxMan
--- !u!222 &642985710
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 642985707}
m_CullTransparentMesh: 1
--- !u!1 &644517399
GameObject:
m_ObjectHideFlags: 0
@@ -2279,6 +2481,82 @@ CanvasRenderer:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 806723448}
m_CullTransparentMesh: 0
--- !u!1 &826167455
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 826167456}
- component: {fileID: 826167458}
- component: {fileID: 826167457}
m_Layer: 5
m_Name: Background
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &826167456
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 826167455}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children:
- {fileID: 1987265555}
m_Father: {fileID: 1767706907}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 1}
m_AnchorMax: {x: 0, y: 1}
m_AnchoredPosition: {x: 10, y: -10}
m_SizeDelta: {x: 20, y: 20}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &826167457
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 826167455}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0}
m_Type: 1
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!222 &826167458
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 826167455}
m_CullTransparentMesh: 1
--- !u!1 &827174940
GameObject:
m_ObjectHideFlags: 0
@@ -2914,7 +3192,7 @@ RectTransform:
- {fileID: 175751363}
- {fileID: 1904789319}
m_Father: {fileID: 339774397}
m_RootOrder: 8
m_RootOrder: 10
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
@@ -2951,7 +3229,7 @@ RectTransform:
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 339774397}
m_RootOrder: 6
m_RootOrder: 8
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
@@ -4114,7 +4392,7 @@ GameObject:
- component: {fileID: 1268276257}
- component: {fileID: 1268276256}
m_Layer: 5
m_Name: Version
m_Name: VrmVersion
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
@@ -4654,7 +4932,7 @@ RectTransform:
- {fileID: 452923209}
- {fileID: 2090837017}
m_Father: {fileID: 339774397}
m_RootOrder: 12
m_RootOrder: 14
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
@@ -4818,7 +5096,7 @@ RectTransform:
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 339774397}
m_RootOrder: 2
m_RootOrder: 6
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
@@ -5363,6 +5641,92 @@ CanvasRenderer:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1767669910}
m_CullTransparentMesh: 0
--- !u!1 &1767706906
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1767706907}
- component: {fileID: 1767706908}
m_Layer: 5
m_Name: ShowBoxMan
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &1767706907
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1767706906}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children:
- {fileID: 826167456}
- {fileID: 642985708}
m_Father: {fileID: 339774397}
m_RootOrder: 7
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 160, y: 20}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &1767706908
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1767706906}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 9085046f02f69544eb97fd06b6048fe2, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Navigation:
m_Mode: 3
m_WrapAround: 0
m_SelectOnUp: {fileID: 0}
m_SelectOnDown: {fileID: 0}
m_SelectOnLeft: {fileID: 0}
m_SelectOnRight: {fileID: 0}
m_Transition: 1
m_Colors:
m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
m_ColorMultiplier: 1
m_FadeDuration: 0.1
m_SpriteState:
m_HighlightedSprite: {fileID: 0}
m_PressedSprite: {fileID: 0}
m_SelectedSprite: {fileID: 0}
m_DisabledSprite: {fileID: 0}
m_AnimationTriggers:
m_NormalTrigger: Normal
m_HighlightedTrigger: Highlighted
m_PressedTrigger: Pressed
m_SelectedTrigger: Selected
m_DisabledTrigger: Disabled
m_Interactable: 1
m_TargetGraphic: {fileID: 826167457}
toggleTransition: 1
graphic: {fileID: 1987265556}
m_Group: {fileID: 0}
onValueChanged:
m_PersistentCalls:
m_Calls: []
m_IsOn: 1
--- !u!1 &1767738853
GameObject:
m_ObjectHideFlags: 0
@@ -5394,7 +5758,7 @@ RectTransform:
- {fileID: 62367395}
- {fileID: 1037763549}
m_Father: {fileID: 339774397}
m_RootOrder: 10
m_RootOrder: 12
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
@@ -5563,30 +5927,30 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
m_version: {fileID: 1268276256}
m_open: {fileID: 2009818433}
m_openModel: {fileID: 2009818433}
m_openMotion: {fileID: 168425996}
m_showBoxMan: {fileID: 1767706908}
m_enableLipSync: {fileID: 935566650}
m_enableAutoBlink: {fileID: 634488422}
m_enableAutoExpression: {fileID: 1767738855}
m_useUrpMaterial: {fileID: 1438613465}
m_useAsync: {fileID: 602093299}
m_src: {fileID: 0}
m_target: {fileID: 802105000}
Root: {fileID: 0}
m_motion: {fileID: 4900000, guid: 08df5151e71aed748b13547492fb8b9a, type: 3}
m_texts:
m_textModelTitle: {fileID: 1111491925}
m_textModelVersion: {fileID: 1045380263}
m_textModelAuthor: {fileID: 854014595}
m_textModelContact: {fileID: 587234270}
m_textModelReference: {fileID: 1181308133}
m_textModelTitle: {fileID: 1636340565}
m_textModelVersion: {fileID: 2105159133}
m_textModelAuthor: {fileID: 827174942}
m_textModelContact: {fileID: 1922159877}
m_textModelReference: {fileID: 806723450}
m_thumbnail: {fileID: 800895694}
m_textPermissionAllowed: {fileID: 1322834811}
m_textPermissionViolent: {fileID: 1242458544}
m_textPermissionSexual: {fileID: 933018279}
m_textPermissionCommercial: {fileID: 852999696}
m_textPermissionOther: {fileID: 1289294209}
m_textDistributionLicense: {fileID: 1476033062}
m_textDistributionOther: {fileID: 1104290798}
m_textPermissionAllowed: {fileID: 1633219309}
m_textPermissionViolent: {fileID: 935554082}
m_textPermissionSexual: {fileID: 928757302}
m_textPermissionCommercial: {fileID: 773923920}
m_textPermissionOther: {fileID: 1172469240}
m_textDistributionLicense: {fileID: 1007924637}
m_textDistributionOther: {fileID: 1199975014}
m_ui:
ToggleMotionTPose: {fileID: 1791103380}
ToggleMotionBVH: {fileID: 1311520910}
@@ -5912,6 +6276,87 @@ CanvasRenderer:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1922159875}
m_CullTransparentMesh: 0
--- !u!1 &1923525314
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1923525315}
- component: {fileID: 1923525317}
- component: {fileID: 1923525316}
m_Layer: 5
m_Name: Text
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &1923525315
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1923525314}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 168425995}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &1923525316
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1923525314}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_FontData:
m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
m_FontSize: 14
m_FontStyle: 0
m_BestFit: 0
m_MinSize: 10
m_MaxSize: 40
m_Alignment: 4
m_AlignByGeometry: 0
m_RichText: 1
m_HorizontalOverflow: 0
m_VerticalOverflow: 0
m_LineSpacing: 1
m_Text: 'Open Motion
'
--- !u!222 &1923525317
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1923525314}
m_CullTransparentMesh: 0
--- !u!1 &1954133884
GameObject:
m_ObjectHideFlags: 0
@@ -6061,7 +6506,9 @@ MonoBehaviour:
m_HorizontalOverflow: 0
m_VerticalOverflow: 0
m_LineSpacing: 1
m_Text: Open
m_Text: 'Open Model
'
--- !u!222 &1963417401
CanvasRenderer:
m_ObjectHideFlags: 0
@@ -6070,6 +6517,81 @@ CanvasRenderer:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1963417398}
m_CullTransparentMesh: 0
--- !u!1 &1987265554
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1987265555}
- component: {fileID: 1987265557}
- component: {fileID: 1987265556}
m_Layer: 5
m_Name: Checkmark
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &1987265555
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1987265554}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 826167456}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 20, y: 20}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &1987265556
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1987265554}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 10901, guid: 0000000000000000f000000000000000, type: 0}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!222 &1987265557
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1987265554}
m_CullTransparentMesh: 1
--- !u!1 &2009818431
GameObject:
m_ObjectHideFlags: 0
@@ -6083,7 +6605,7 @@ GameObject:
- component: {fileID: 2009818434}
- component: {fileID: 2009818433}
m_Layer: 5
m_Name: Open
m_Name: OpenModel
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0

View File

@@ -11,12 +11,18 @@ namespace UniVRM10.VRM10Viewer
{
public class VRM10ViewerUI : MonoBehaviour
{
[Header("UI")]
[SerializeField]
Text m_version = default;
[Header("UI")]
[SerializeField]
Button m_open = default;
Button m_openModel = default;
[SerializeField]
Button m_openMotion = default;
[SerializeField]
Toggle m_showBoxMan = default;
[SerializeField]
Toggle m_enableLipSync = default;
@@ -41,14 +47,26 @@ namespace UniVRM10.VRM10Viewer
GameObject Root = default;
VRM10Motion m_src = default;
IMotion m_src = default;
public IMotion Motion
{
get { return m_src; }
set
{
if (m_src != null)
{
m_src.Dispose();
}
m_src = value;
}
}
private CancellationTokenSource _cancellationTokenSource;
[Serializable]
class TextFields
{
[SerializeField, Header("Info")]
[SerializeField]
Text m_textModelTitle = default;
[SerializeField]
Text m_textModelVersion = default;
@@ -77,6 +95,28 @@ namespace UniVRM10.VRM10Viewer
[SerializeField]
Text m_textDistributionOther = default;
public void Reset()
{
var texts = GameObject.FindObjectsOfType<Text>();
m_textModelTitle = texts.First(x => x.name == "Title");
m_textModelVersion = texts.First(x => x.name == "Version");
m_textModelAuthor = texts.First(x => x.name == "Author");
m_textModelContact = texts.First(x => x.name == "Contact");
m_textModelReference = texts.First(x => x.name == "Reference");
m_textPermissionAllowed = texts.First(x => x.name == "AllowedUser");
m_textPermissionViolent = texts.First(x => x.name == "Violent");
m_textPermissionSexual = texts.First(x => x.name == "Sexual");
m_textPermissionCommercial = texts.First(x => x.name == "Commercial");
m_textPermissionOther = texts.First(x => x.name == "Other");
m_textDistributionLicense = texts.First(x => x.name == "LicenseType");
m_textDistributionOther = texts.First(x => x.name == "OtherLicense");
var images = GameObject.FindObjectsOfType<RawImage>();
m_thumbnail = images.First(x => x.name == "RawImage");
}
public void Start()
{
m_textModelTitle.text = "";
@@ -151,6 +191,16 @@ namespace UniVRM10.VRM10Viewer
[SerializeField]
ToggleGroup ToggleMotion = default;
public void Reset()
{
var toggles = GameObject.FindObjectsOfType<Toggle>();
ToggleMotionTPose = toggles.First(x => x.name == "TPose");
ToggleMotionBVH = toggles.First(x => x.name == "BVH");
var groups = GameObject.FindObjectsOfType<ToggleGroup>();
ToggleMotion = groups.First(x => x.name == "_Motion_");
}
public bool IsBvhEnabled
{
get => ToggleMotion.ActiveToggles().FirstOrDefault() == ToggleMotionBVH;
@@ -167,15 +217,22 @@ namespace UniVRM10.VRM10Viewer
private void Reset()
{
var buttons = GameObject.FindObjectsOfType<Button>();
m_open = buttons.First(x => x.name == "Open");
m_openModel = buttons.First(x => x.name == "OpenModel");
m_openMotion = buttons.First(x => x.name == "OpenMotion");
var toggles = GameObject.FindObjectsOfType<Toggle>();
m_showBoxMan = toggles.First(x => x.name == "ShowBoxMan");
m_enableLipSync = toggles.First(x => x.name == "EnableLipSync");
m_enableAutoBlink = toggles.First(x => x.name == "EnableAutoBlink");
m_enableAutoExpression = toggles.First(x => x.name == "EnableAutoExpression");
m_useUrpMaterial = toggles.First(x => x.name == "UseUrpMaterial");
m_useAsync = toggles.First(x => x.name == "UseAsync");
var texts = GameObject.FindObjectsOfType<Text>();
m_version = texts.First(x => x.name == "Version");
m_version = texts.First(x => x.name == "VrmVersion");
m_texts.Reset();
m_ui.Reset();
m_target = GameObject.FindObjectOfType<VRM10TargetMover>().gameObject;
}
@@ -185,13 +242,16 @@ namespace UniVRM10.VRM10Viewer
private void Start()
{
m_version.text = string.Format("VRMViewer {0}.{1}",
VRMVersion.MAJOR, VRMVersion.MINOR);
m_open.onClick.AddListener(OnOpenClicked);
VRMVersion.MAJOR, VRMVersion.MINOR);
m_openModel.onClick.AddListener(OnOpenModelClicked);
m_openMotion.onClick.AddListener(OnOpenMotionClicked);
// load initial bvh
if (m_motion != null)
{
m_src = VRM10Motion.LoadBvhFromText(m_motion.text);
Motion = BvhMotion.LoadBvhFromText(m_motion.text);
}
string[] cmds = System.Environment.GetCommandLineArgs();
@@ -213,13 +273,6 @@ namespace UniVRM10.VRM10Viewer
private void Update()
{
if (m_loaded != null)
{
m_loaded.EnableLipSyncValue = m_enableLipSync.isOn;
m_loaded.EnableBlinkValue = m_enableAutoBlink.isOn;
m_loaded.EnableAutoExpressionValue = m_enableAutoExpression.isOn;
}
if (Input.GetKeyDown(KeyCode.Tab))
{
if (Root != null) Root.SetActive(!Root.activeSelf);
@@ -233,11 +286,20 @@ namespace UniVRM10.VRM10Viewer
}
}
if (Motion != null)
{
Motion.ShowBoxMan(m_showBoxMan.isOn);
}
if (m_loaded != null)
{
if (m_ui.IsBvhEnabled && m_src != null)
m_loaded.EnableLipSyncValue = m_enableLipSync.isOn;
m_loaded.EnableBlinkValue = m_enableAutoBlink.isOn;
m_loaded.EnableAutoExpressionValue = m_enableAutoExpression.isOn;
if (m_ui.IsBvhEnabled && Motion != null)
{
VRM10Retarget.Retarget(m_src.ControlRig, (m_loaded.ControlRig, m_loaded.ControlRig));
VRM10Retarget.Retarget(Motion.ControlRig, (m_loaded.ControlRig, m_loaded.ControlRig));
}
else
{
@@ -246,10 +308,10 @@ namespace UniVRM10.VRM10Viewer
}
}
void OnOpenClicked()
void OnOpenModelClicked()
{
#if UNITY_STANDALONE_WIN
var path = VRM10FileDialogForWindows.FileDialog("open VRM", "vrm", "bvh");
var path = VRM10FileDialogForWindows.FileDialog("open VRM", "vrm");
#elif UNITY_EDITOR
var path = UnityEditor.EditorUtility.OpenFilePanel("Open VRM", "", "vrm");
#else
@@ -261,12 +323,6 @@ namespace UniVRM10.VRM10Viewer
}
var ext = Path.GetExtension(path).ToLower();
if (ext == ".bvh")
{
m_src = VRM10Motion.LoadBvhFromPath(path);
return;
}
if (ext != ".vrm")
{
Debug.LogWarning($"{path} is not vrm");
@@ -276,6 +332,31 @@ namespace UniVRM10.VRM10Viewer
LoadModel(path);
}
async void OnOpenMotionClicked()
{
#if UNITY_STANDALONE_WIN
var path = VRM10FileDialogForWindows.FileDialog("open Motion", "bvh", "gltf", "glb");
#elif UNITY_EDITOR
var path = UnityEditor.EditorUtility.OpenFilePanel("Open Motion", "", "bvh");
#else
var path = Application.dataPath + "/default.bvh";
#endif
if (string.IsNullOrEmpty(path))
{
return;
}
var ext = Path.GetExtension(path).ToLower();
if (ext == ".bvh")
{
Motion = BvhMotion.LoadBvhFromPath(path);
return;
}
// gltf, glb etc...
Motion = await VrmAnimation.LoadVrmAnimationFromPathAsync(path);
}
static IMaterialDescriptorGenerator GetVrmMaterialDescriptorGenerator(bool useUrp)
{
if (useUrp)