mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-08-22 02:24:57 -05:00
add VRM10FirstPersonSample
This commit is contained in:
8
Assets/VRM10/Samples/VRM10FirstPersonSample.meta
Normal file
8
Assets/VRM10/Samples/VRM10FirstPersonSample.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 63991f54f0175cf4294770b968b5b456
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1833
Assets/VRM10/Samples/VRM10FirstPersonSample/FirstPersonSample.unity
Normal file
1833
Assets/VRM10/Samples/VRM10FirstPersonSample/FirstPersonSample.unity
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 056ca4a0e47b8b5408a1c557768e188b
|
||||
timeCreated: 1520832729
|
||||
licenseType: Free
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,22 @@
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
|
||||
namespace UniVRM10.FirstPersonSample
|
||||
{
|
||||
public class VRM10CanvasManager : MonoBehaviour
|
||||
{
|
||||
[SerializeField]
|
||||
public Button LoadVRMButton;
|
||||
|
||||
[SerializeField]
|
||||
public Button LoadBVHButton;
|
||||
|
||||
private void Reset()
|
||||
{
|
||||
LoadVRMButton = GameObject.FindObjectsOfType<Button>().FirstOrDefault(x => x.name == "LoadVRM");
|
||||
LoadBVHButton = GameObject.FindObjectsOfType<Button>().FirstOrDefault(x => x.name == "LoadBVH");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 58bd4ef7b3a863142ae9960c21106ba3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,118 @@
|
||||
#if UNITY_STANDALONE_WIN
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
#endif
|
||||
|
||||
|
||||
namespace UniVRM10.FirstPersonSample
|
||||
{
|
||||
public static class VRM10FileDialogForWindows
|
||||
{
|
||||
#if UNITY_STANDALONE_WIN
|
||||
#region GetOpenFileName
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
|
||||
public class OpenFileName
|
||||
{
|
||||
public int structSize = 0;
|
||||
public IntPtr dlgOwner = IntPtr.Zero;
|
||||
public IntPtr instance = IntPtr.Zero;
|
||||
public String filter = null;
|
||||
public String customFilter = null;
|
||||
public int maxCustFilter = 0;
|
||||
public int filterIndex = 0;
|
||||
public String file = null;
|
||||
public int maxFile = 0;
|
||||
public String fileTitle = null;
|
||||
public int maxFileTitle = 0;
|
||||
public String initialDir = null;
|
||||
public String title = null;
|
||||
public int flags = 0;
|
||||
public short fileOffset = 0;
|
||||
public short fileExtension = 0;
|
||||
public String defExt = null;
|
||||
public IntPtr custData = IntPtr.Zero;
|
||||
public IntPtr hook = IntPtr.Zero;
|
||||
public String templateName = null;
|
||||
public IntPtr reservedPtr = IntPtr.Zero;
|
||||
public int reservedInt = 0;
|
||||
public int flagsEx = 0;
|
||||
}
|
||||
|
||||
[DllImport("Comdlg32.dll", SetLastError = true, ThrowOnUnmappableChar = true, CharSet = CharSet.Auto)]
|
||||
public static extern bool GetOpenFileName([In, Out] OpenFileName ofn);
|
||||
/*
|
||||
public static bool GetOpenFileName1([In, Out] OpenFileName ofn)
|
||||
{
|
||||
return GetOpenFileName(ofn);
|
||||
}
|
||||
*/
|
||||
|
||||
[DllImport("Comdlg32.dll", SetLastError = true, CharSet = CharSet.Auto)]
|
||||
private static extern bool GetSaveFileName([In, Out] OpenFileName ofn);
|
||||
|
||||
static string Filter(params string[] filters)
|
||||
{
|
||||
return string.Join("\0", filters) + "\0";
|
||||
}
|
||||
public static string FileDialog(string title, params string[] extensions)
|
||||
{
|
||||
OpenFileName ofn = new OpenFileName();
|
||||
ofn.structSize = Marshal.SizeOf(ofn);
|
||||
|
||||
var filters = new List<string>();
|
||||
filters.Add("All Files"); filters.Add("*.*");
|
||||
foreach(var ext in extensions)
|
||||
{
|
||||
filters.Add(ext); filters.Add("*" + ext);
|
||||
}
|
||||
ofn.filter = Filter(filters.ToArray());
|
||||
ofn.filterIndex = 2;
|
||||
ofn.file = new string(new char[256]);
|
||||
ofn.maxFile = ofn.file.Length;
|
||||
ofn.fileTitle = new string(new char[64]);
|
||||
ofn.maxFileTitle = ofn.fileTitle.Length;
|
||||
ofn.initialDir = UnityEngine.Application.dataPath;
|
||||
ofn.title = title;
|
||||
//ofn.defExt = "PNG";
|
||||
ofn.flags = 0x00080000 | 0x00001000 | 0x00000800 | 0x00000200 | 0x00000008;//OFN_EXPLORER|OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST| OFN_ALLOWMULTISELECT|OFN_NOCHANGEDIR
|
||||
if (!GetOpenFileName(ofn))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return ofn.file;
|
||||
}
|
||||
public static string SaveDialog(string title, string path)
|
||||
{
|
||||
var extension = Path.GetExtension(path);
|
||||
OpenFileName ofn = new OpenFileName();
|
||||
ofn.structSize = Marshal.SizeOf(ofn);
|
||||
ofn.filter = Filter("All Files", "*.*", extension, "*" + extension);
|
||||
ofn.filterIndex = 2;
|
||||
var chars = new char[256];
|
||||
var it = Path.GetFileName(path).GetEnumerator();
|
||||
for (int i = 0; i < chars.Length && it.MoveNext(); ++i)
|
||||
{
|
||||
chars[i] = it.Current;
|
||||
}
|
||||
ofn.file = new string(chars);
|
||||
ofn.maxFile = ofn.file.Length;
|
||||
ofn.fileTitle = new string(new char[64]);
|
||||
ofn.maxFileTitle = ofn.fileTitle.Length;
|
||||
ofn.initialDir = Path.GetDirectoryName(path);
|
||||
ofn.title = title;
|
||||
//ofn.defExt = "PNG";
|
||||
ofn.flags = 0x00000002 | 0x00000004; // OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY;
|
||||
if (!GetSaveFileName(ofn))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return ofn.file;
|
||||
}
|
||||
#endregion
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2e637d7baec8ac742bcb7709db745193
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,36 @@
|
||||
using UnityEngine;
|
||||
using UniGLTF;
|
||||
|
||||
|
||||
namespace UniVRM10
|
||||
{
|
||||
public class VRM10LookTarget : MonoBehaviour
|
||||
{
|
||||
[SerializeField]
|
||||
public Transform Target;
|
||||
|
||||
[SerializeField]
|
||||
Vector3 m_offset = new Vector3(0, 0.05f, 0);
|
||||
|
||||
[SerializeField, Range(0, 3.0f)]
|
||||
float m_distance = 0.7f;
|
||||
|
||||
public VRM10OffsetOnTransform m_offsetTransform;
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (Target != m_offsetTransform.Transform)
|
||||
{
|
||||
m_offsetTransform = VRM10OffsetOnTransform.Create(Target);
|
||||
}
|
||||
|
||||
var target = m_offsetTransform.Transform;
|
||||
if (target != null)
|
||||
{
|
||||
var targetPosition = target.position + m_offset;
|
||||
transform.position = targetPosition + (m_offsetTransform.WorldMatrix.ExtractRotation() * Vector3.forward) * m_distance;
|
||||
transform.LookAt(targetPosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b74319fb726e30c4ca99bd741af8bd3c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,61 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
namespace UniVRM10
|
||||
{
|
||||
[Serializable]
|
||||
public struct VRM10OffsetOnTransform
|
||||
{
|
||||
public Transform Transform;
|
||||
public Matrix4x4 OffsetRotation;
|
||||
|
||||
public Matrix4x4 WorldMatrix
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Transform == null) return Matrix4x4.identity;
|
||||
return Transform.localToWorldMatrix * OffsetRotation;
|
||||
}
|
||||
}
|
||||
|
||||
public Vector3 WorldForward
|
||||
{
|
||||
get
|
||||
{
|
||||
var m = WorldMatrix;
|
||||
return m.GetColumn(2); // zaxis
|
||||
}
|
||||
}
|
||||
|
||||
Matrix4x4 m_initialLocalMatrix;
|
||||
public void Setup()
|
||||
{
|
||||
if (Transform == null) return;
|
||||
m_initialLocalMatrix = Transform.parent.worldToLocalMatrix * Transform.localToWorldMatrix;
|
||||
}
|
||||
|
||||
public Matrix4x4 InitialWorldMatrix
|
||||
{
|
||||
get
|
||||
{
|
||||
return Transform.parent.localToWorldMatrix * m_initialLocalMatrix;
|
||||
}
|
||||
}
|
||||
|
||||
public static VRM10OffsetOnTransform Create(Transform transform)
|
||||
{
|
||||
var coordinate = new VRM10OffsetOnTransform
|
||||
{
|
||||
Transform = transform
|
||||
};
|
||||
|
||||
if (transform != null)
|
||||
{
|
||||
coordinate.OffsetRotation = transform.worldToLocalMatrix.RotationToWorldAxis();
|
||||
}
|
||||
|
||||
return coordinate;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 463fb7b24167d6a49a43bbcc4dfd42b6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,142 @@
|
||||
#pragma warning disable 0414
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using UniGLTF;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
namespace UniVRM10.FirstPersonSample
|
||||
{
|
||||
public class VRM10RuntimeLoader : MonoBehaviour
|
||||
{
|
||||
[SerializeField, Header("GUI")]
|
||||
VRM10CanvasManager m_canvas = default;
|
||||
|
||||
[SerializeField]
|
||||
VRM10LookTarget m_faceCamera = default;
|
||||
|
||||
[SerializeField, Header("loader")]
|
||||
UniHumanoid.HumanPoseTransfer m_source;
|
||||
|
||||
[SerializeField]
|
||||
UniHumanoid.HumanPoseTransfer m_target;
|
||||
|
||||
[SerializeField, Header("runtime")]
|
||||
VRM10Controller m_firstPerson;
|
||||
|
||||
async Task SetupTargetAsync(UniHumanoid.HumanPoseTransfer m_target, bool visible)
|
||||
{
|
||||
if (m_target != null)
|
||||
{
|
||||
m_target.Source = m_source;
|
||||
m_target.SourceType = UniHumanoid.HumanPoseTransfer.HumanPoseTransferSourceType.HumanPoseTransfer;
|
||||
|
||||
m_firstPerson = m_target.GetComponent<VRM10Controller>();
|
||||
|
||||
var animator = m_target.GetComponent<Animator>();
|
||||
if (animator != null)
|
||||
{
|
||||
await m_firstPerson.Vrm.FirstPerson.SetupAsync(m_firstPerson.gameObject, visible);
|
||||
|
||||
if (m_faceCamera != null)
|
||||
{
|
||||
m_faceCamera.Target = animator.GetBoneTransform(HumanBodyBones.Head);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
if (m_canvas == null)
|
||||
{
|
||||
Debug.LogWarning("no canvas");
|
||||
return;
|
||||
}
|
||||
|
||||
m_canvas.LoadVRMButton.onClick.AddListener(LoadVRMClicked);
|
||||
m_canvas.LoadBVHButton.onClick.AddListener(LoadBVHClicked);
|
||||
}
|
||||
|
||||
async void LoadVRMClicked()
|
||||
{
|
||||
#if UNITY_STANDALONE_WIN
|
||||
var path = VRM10FileDialogForWindows.FileDialog("open VRM", ".vrm");
|
||||
#elif UNITY_EDITOR
|
||||
var path = UnityEditor.EditorUtility.OpenFilePanel("Open VRM", "", "vrm");
|
||||
#else
|
||||
var path = Application.dataPath + "/default.vrm";
|
||||
#endif
|
||||
if (string.IsNullOrEmpty(path))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// GLB形式でJSONを取得しParseします
|
||||
// VRM extension を parse します
|
||||
var data = new GlbFileParser(path).Parse();
|
||||
Vrm10Data.TryParseOrMigrate(data, true, out Vrm10Data vrm);
|
||||
using (var context = new Vrm10Importer(vrm))
|
||||
{
|
||||
// metaを取得(todo: thumbnailテクスチャのロード)
|
||||
var meta = vrm.VrmExtension.Meta;
|
||||
Debug.LogFormat("meta: title:{0}", meta.Name);
|
||||
|
||||
// ParseしたJSONをシーンオブジェクトに変換していく
|
||||
var loaded = await context.LoadAsync();
|
||||
|
||||
var root = loaded.gameObject;
|
||||
|
||||
root.transform.SetParent(transform, false);
|
||||
|
||||
// add motion
|
||||
var humanPoseTransfer = root.AddComponent<UniHumanoid.HumanPoseTransfer>();
|
||||
if (m_target != null)
|
||||
{
|
||||
GameObject.Destroy(m_target.gameObject);
|
||||
}
|
||||
m_target = humanPoseTransfer;
|
||||
await SetupTargetAsync(m_target, visible: false);
|
||||
|
||||
//メッシュを表示します
|
||||
// loaded.ShowMeshes();
|
||||
}
|
||||
}
|
||||
|
||||
void LoadBVHClicked()
|
||||
{
|
||||
#if UNITY_STANDALONE_WIN
|
||||
var path = VRM10FileDialogForWindows.FileDialog("open BVH", ".bvh");
|
||||
if (!string.IsNullOrEmpty(path))
|
||||
{
|
||||
LoadBvh(path);
|
||||
}
|
||||
#elif UNITY_EDITOR
|
||||
var path = UnityEditor.EditorUtility.OpenFilePanel("Open BVH", "", "bvh");
|
||||
if (!string.IsNullOrEmpty(path))
|
||||
{
|
||||
LoadBvh(path);
|
||||
}
|
||||
#else
|
||||
LoadBvh(Application.dataPath + "/default.bvh");
|
||||
#endif
|
||||
}
|
||||
|
||||
void LoadBvh(string path)
|
||||
{
|
||||
Debug.LogFormat("ImportBvh: {0}", path);
|
||||
var context = new UniHumanoid.BvhImporterContext();
|
||||
|
||||
context.Parse(path);
|
||||
context.Load();
|
||||
|
||||
if (m_source != null)
|
||||
{
|
||||
GameObject.Destroy(m_source.gameObject);
|
||||
}
|
||||
m_source = context.Root.GetComponent<UniHumanoid.HumanPoseTransfer>();
|
||||
|
||||
var task = SetupTargetAsync(m_target, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bd151410f22d0f6409cf4b17c03a3c6e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user