mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-09-09 20:38:56 -05:00
WIP UniGLTF with VrmLib.Model
This commit is contained in:
@@ -3,9 +3,9 @@ using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using System.Threading.Tasks;
|
||||
using System.Text;
|
||||
using VRMShaders;
|
||||
|
||||
|
||||
namespace UniGLTF
|
||||
{
|
||||
/// <summary>
|
||||
@@ -88,8 +88,6 @@ namespace UniGLTF
|
||||
MeasureTime = new ImporterContextSpeedLog().MeasureTime;
|
||||
}
|
||||
|
||||
var inverter = InvertAxis.Create();
|
||||
|
||||
if (Root == null)
|
||||
{
|
||||
Root = new GameObject("GLTF");
|
||||
@@ -116,6 +114,20 @@ namespace UniGLTF
|
||||
await LoadMaterialsAsync();
|
||||
}
|
||||
|
||||
await LoadGeometryAsync(MeasureTime);
|
||||
|
||||
using (MeasureTime("AnimationImporter"))
|
||||
{
|
||||
AnimationImporter.Import(this);
|
||||
}
|
||||
|
||||
await OnLoadModel(m_awaitCaller, MeasureTime);
|
||||
}
|
||||
|
||||
protected virtual async Task LoadGeometryAsync(Func<string, IDisposable> MeasureTime)
|
||||
{
|
||||
var inverter = InvertAxis.Create();
|
||||
|
||||
var meshImporter = new MeshImporter();
|
||||
for (int i = 0; i < GLTF.meshes.Count; ++i)
|
||||
{
|
||||
@@ -164,13 +176,6 @@ namespace UniGLTF
|
||||
}
|
||||
}
|
||||
await m_awaitCaller.NextFrame();
|
||||
|
||||
using (MeasureTime("AnimationImporter"))
|
||||
{
|
||||
AnimationImporter.Import(this);
|
||||
}
|
||||
|
||||
await OnLoadModel(m_awaitCaller, MeasureTime);
|
||||
}
|
||||
|
||||
public async Task LoadMaterialsAsync()
|
||||
|
||||
@@ -84,10 +84,12 @@ namespace UniVRM10.Samples
|
||||
m_textDistributionOther.text = "";
|
||||
}
|
||||
|
||||
public void UpdateMeta(VRM10Controller context)
|
||||
public void UpdateMeta(VRM10MetaObject meta)
|
||||
{
|
||||
// var meta = context.ReadMeta(true);
|
||||
var meta = context.Meta;
|
||||
if (meta == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_textModelTitle.text = meta.Name;
|
||||
m_textModelVersion.text = meta.Version;
|
||||
@@ -306,28 +308,17 @@ namespace UniVRM10.Samples
|
||||
{
|
||||
case ".vrm":
|
||||
{
|
||||
var parser =new UniGLTF.GltfParser();
|
||||
var parser = new UniGLTF.GltfParser();
|
||||
parser.ParsePath(path);
|
||||
|
||||
// context.Load();
|
||||
// context.ShowMeshes();
|
||||
// context.EnableUpdateWhenOffscreen();
|
||||
// context.ShowMeshes();
|
||||
|
||||
var model = UniVRM10.VrmLoader.CreateVrmModel(parser);
|
||||
|
||||
// UniVRM-0.XXのコンポーネントを構築する
|
||||
var assets = UniVRM10.RuntimeUnityBuilder.ToUnityAsset(model, showMesh: false);
|
||||
|
||||
// showRenderer = false のときに後で表示する例
|
||||
foreach (var renderer in assets.Renderers)
|
||||
using (var loader = new RuntimeUnityBuilder(parser))
|
||||
{
|
||||
renderer.enabled = true;
|
||||
loader.Load();
|
||||
loader.ShowMeshes();
|
||||
loader.EnableUpdateWhenOffscreen();
|
||||
var destroyer = loader.DisposeOnGameObjectDestroyed();
|
||||
SetModel(destroyer.gameObject);
|
||||
}
|
||||
|
||||
UniVRM10.ComponentBuilder.Build10(model, assets);
|
||||
|
||||
SetModel(assets.Root);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -337,12 +328,15 @@ namespace UniVRM10.Samples
|
||||
var parser = new GltfParser();
|
||||
parser.ParseGlb(file);
|
||||
|
||||
var context = new UniGLTF.ImporterContext(parser);
|
||||
context.Load();
|
||||
context.ShowMeshes();
|
||||
context.EnableUpdateWhenOffscreen();
|
||||
context.ShowMeshes();
|
||||
SetModel(context.Root);
|
||||
using (var loader = new UniGLTF.ImporterContext(parser))
|
||||
{
|
||||
loader.Load();
|
||||
loader.ShowMeshes();
|
||||
loader.EnableUpdateWhenOffscreen();
|
||||
loader.ShowMeshes();
|
||||
var destroyer = loader.DisposeOnGameObjectDestroyed();
|
||||
SetModel(destroyer.gameObject);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -352,12 +346,15 @@ namespace UniVRM10.Samples
|
||||
var parser = new GltfParser();
|
||||
parser.ParsePath(path);
|
||||
|
||||
var context = new UniGLTF.ImporterContext(parser);
|
||||
context.Load();
|
||||
context.ShowMeshes();
|
||||
context.EnableUpdateWhenOffscreen();
|
||||
context.ShowMeshes();
|
||||
SetModel(context.Root);
|
||||
using (var loader = new UniGLTF.ImporterContext(parser))
|
||||
{
|
||||
loader.Load();
|
||||
loader.ShowMeshes();
|
||||
loader.EnableUpdateWhenOffscreen();
|
||||
loader.ShowMeshes();
|
||||
var destroyer = loader.DisposeOnGameObjectDestroyed();
|
||||
SetModel(destroyer.gameObject);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -382,19 +379,22 @@ namespace UniVRM10.Samples
|
||||
if (go != null)
|
||||
{
|
||||
m_controller = go.GetComponent<VRM10Controller>();
|
||||
|
||||
m_texts.UpdateMeta(m_controller);
|
||||
|
||||
m_controller.Controller.UpdateType = VRM10Controller.VRM10ControllerImpl.UpdateTypes.LateUpdate; // after HumanPoseTransfer's setPose
|
||||
if (m_controller != null)
|
||||
{
|
||||
m_loaded = go.AddComponent<HumanPoseTransfer>();
|
||||
m_loaded.Source = m_src;
|
||||
m_loaded.SourceType = HumanPoseTransfer.HumanPoseTransferSourceType.HumanPoseTransfer;
|
||||
|
||||
m_lipSync = go.AddComponent<AIUEO>();
|
||||
m_blink = go.AddComponent<Blinker>();
|
||||
m_texts.UpdateMeta(m_controller.Meta);
|
||||
|
||||
m_controller.LookAt.Gaze = m_target.transform;
|
||||
m_controller.Controller.UpdateType = VRM10Controller.VRM10ControllerImpl.UpdateTypes.LateUpdate; // after HumanPoseTransfer's setPose
|
||||
{
|
||||
m_loaded = go.AddComponent<HumanPoseTransfer>();
|
||||
m_loaded.Source = m_src;
|
||||
m_loaded.SourceType = HumanPoseTransfer.HumanPoseTransferSourceType.HumanPoseTransfer;
|
||||
|
||||
m_lipSync = go.AddComponent<AIUEO>();
|
||||
m_blink = go.AddComponent<Blinker>();
|
||||
|
||||
m_controller.LookAt.Gaze = m_target.transform;
|
||||
}
|
||||
}
|
||||
|
||||
var animation = go.GetComponent<Animation>();
|
||||
@@ -402,7 +402,6 @@ namespace UniVRM10.Samples
|
||||
{
|
||||
animation.Play(animation.clip.name);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,132 +8,132 @@ namespace UniVRM10
|
||||
{
|
||||
public static class EditorUnityBuilder
|
||||
{
|
||||
static public ModelAsset ToUnityAsset(VrmLib.Model model, string assetPath, IExternalUnityObject scriptedImporter)
|
||||
{
|
||||
var modelAsset = new ModelAsset();
|
||||
CreateTextureAsset(model, modelAsset, scriptedImporter);
|
||||
CreateMaterialAsset(model, modelAsset, scriptedImporter);
|
||||
CreateMeshAsset(model, modelAsset);
|
||||
// static public ModelAsset ToUnityAsset(VrmLib.Model model, string assetPath, IExternalUnityObject scriptedImporter)
|
||||
// {
|
||||
// var modelAsset = new ModelAsset();
|
||||
// CreateTextureAsset(model, modelAsset, scriptedImporter);
|
||||
// CreateMaterialAsset(model, modelAsset, scriptedImporter);
|
||||
// CreateMeshAsset(model, modelAsset);
|
||||
|
||||
// node
|
||||
RuntimeUnityBuilder.CreateNodes(model.Root, null, modelAsset.Map.Nodes);
|
||||
modelAsset.Root = modelAsset.Map.Nodes[model.Root];
|
||||
// // node
|
||||
// RuntimeUnityBuilder.CreateNodes(model.Root, null, modelAsset.Map.Nodes);
|
||||
// modelAsset.Root = modelAsset.Map.Nodes[model.Root];
|
||||
|
||||
// renderer
|
||||
var map = modelAsset.Map;
|
||||
foreach (var (node, go) in map.Nodes)
|
||||
{
|
||||
if (node.MeshGroup is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
// // renderer
|
||||
// var map = modelAsset.Map;
|
||||
// foreach (var (node, go) in map.Nodes)
|
||||
// {
|
||||
// if (node.MeshGroup is null)
|
||||
// {
|
||||
// continue;
|
||||
// }
|
||||
|
||||
if (node.MeshGroup.Meshes.Count > 1)
|
||||
{
|
||||
throw new NotImplementedException("invalid isolated vertexbuffer");
|
||||
}
|
||||
// if (node.MeshGroup.Meshes.Count > 1)
|
||||
// {
|
||||
// throw new NotImplementedException("invalid isolated vertexbuffer");
|
||||
// }
|
||||
|
||||
var renderer = RuntimeUnityBuilder.CreateRenderer(node, go, map);
|
||||
map.Renderers.Add(node, renderer);
|
||||
modelAsset.Renderers.Add(renderer);
|
||||
}
|
||||
// var renderer = RuntimeUnityBuilder.CreateRenderer(node, go, map);
|
||||
// map.Renderers.Add(node, renderer);
|
||||
// modelAsset.Renderers.Add(renderer);
|
||||
// }
|
||||
|
||||
if (model.Vrm != null)
|
||||
{
|
||||
// humanoid
|
||||
var humanoid = modelAsset.Root.AddComponent<MeshUtility.Humanoid>();
|
||||
humanoid.AssignBones(modelAsset.Map.Nodes.Select(x => (x.Key.HumanoidBone.GetValueOrDefault().ToUnity(), x.Value.transform)));
|
||||
modelAsset.HumanoidAvatar = humanoid.CreateAvatar();
|
||||
modelAsset.HumanoidAvatar.name = "VRM";
|
||||
// if (model.Vrm != null)
|
||||
// {
|
||||
// // humanoid
|
||||
// var humanoid = modelAsset.Root.AddComponent<MeshUtility.Humanoid>();
|
||||
// humanoid.AssignBones(modelAsset.Map.Nodes.Select(x => (x.Key.HumanoidBone.GetValueOrDefault().ToUnity(), x.Value.transform)));
|
||||
// modelAsset.HumanoidAvatar = humanoid.CreateAvatar();
|
||||
// modelAsset.HumanoidAvatar.name = "VRM";
|
||||
|
||||
var animator = modelAsset.Root.AddComponent<Animator>();
|
||||
animator.avatar = modelAsset.HumanoidAvatar;
|
||||
}
|
||||
// var animator = modelAsset.Root.AddComponent<Animator>();
|
||||
// animator.avatar = modelAsset.HumanoidAvatar;
|
||||
// }
|
||||
|
||||
return modelAsset;
|
||||
}
|
||||
// return modelAsset;
|
||||
// }
|
||||
|
||||
static private void CreateTextureAsset(VrmLib.Model model, ModelAsset modelAsset, IExternalUnityObject scriptedImporter)
|
||||
{
|
||||
var externalObjects = scriptedImporter.GetExternalUnityObjects<Texture2D>();
|
||||
// static private void CreateTextureAsset(VrmLib.Model model, ModelAsset modelAsset, IExternalUnityObject scriptedImporter)
|
||||
// {
|
||||
// var externalObjects = scriptedImporter.GetExternalUnityObjects<Texture2D>();
|
||||
|
||||
// textures
|
||||
for (int i = 0; i < model.Textures.Count; ++i)
|
||||
{
|
||||
if (model.Textures[i] is VrmLib.ImageTexture imageTexture)
|
||||
{
|
||||
if (string.IsNullOrEmpty(model.Textures[i].Name))
|
||||
{
|
||||
model.Textures[i].Name = string.Format("{0}_img{1}", model.Root.Name, i);
|
||||
}
|
||||
if (externalObjects.ContainsKey(model.Textures[i].Name))
|
||||
{
|
||||
modelAsset.Map.Textures.Add(imageTexture, externalObjects[model.Textures[i].Name]);
|
||||
modelAsset.Textures.Add(externalObjects[model.Textures[i].Name]);
|
||||
}
|
||||
else
|
||||
{
|
||||
var name = !string.IsNullOrEmpty(imageTexture.Name)
|
||||
? imageTexture.Name
|
||||
: string.Format("{0}_img{1}", model.Root.Name, i);
|
||||
// // textures
|
||||
// for (int i = 0; i < model.Textures.Count; ++i)
|
||||
// {
|
||||
// if (model.Textures[i] is VrmLib.ImageTexture imageTexture)
|
||||
// {
|
||||
// if (string.IsNullOrEmpty(model.Textures[i].Name))
|
||||
// {
|
||||
// model.Textures[i].Name = string.Format("{0}_img{1}", model.Root.Name, i);
|
||||
// }
|
||||
// if (externalObjects.ContainsKey(model.Textures[i].Name))
|
||||
// {
|
||||
// modelAsset.Map.Textures.Add(imageTexture, externalObjects[model.Textures[i].Name]);
|
||||
// modelAsset.Textures.Add(externalObjects[model.Textures[i].Name]);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// var name = !string.IsNullOrEmpty(imageTexture.Name)
|
||||
// ? imageTexture.Name
|
||||
// : string.Format("{0}_img{1}", model.Root.Name, i);
|
||||
|
||||
var texture = RuntimeUnityBuilder.CreateTexture(imageTexture);
|
||||
texture.name = name;
|
||||
// var texture = RuntimeUnityBuilder.CreateTexture(imageTexture);
|
||||
// texture.name = name;
|
||||
|
||||
modelAsset.Map.Textures.Add(imageTexture, texture);
|
||||
modelAsset.Textures.Add(texture);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"{i} not ImageTexture");
|
||||
}
|
||||
}
|
||||
}
|
||||
// modelAsset.Map.Textures.Add(imageTexture, texture);
|
||||
// modelAsset.Textures.Add(texture);
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// Debug.LogWarning($"{i} not ImageTexture");
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
static private void CreateMaterialAsset(VrmLib.Model model, ModelAsset modelAsset, IExternalUnityObject scriptedImporter)
|
||||
{
|
||||
var externalObjects = scriptedImporter.GetExternalUnityObjects<UnityEngine.Material>();
|
||||
// static private void CreateMaterialAsset(VrmLib.Model model, ModelAsset modelAsset, IExternalUnityObject scriptedImporter)
|
||||
// {
|
||||
// var externalObjects = scriptedImporter.GetExternalUnityObjects<UnityEngine.Material>();
|
||||
|
||||
foreach (var src in model.Materials)
|
||||
{
|
||||
if (externalObjects.ContainsKey(src.Name))
|
||||
{
|
||||
modelAsset.Map.Materials.Add(src, externalObjects[src.Name]);
|
||||
modelAsset.Materials.Add(externalObjects[src.Name]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: material has VertexColor
|
||||
var material = RuntimeUnityMaterialBuilder.CreateMaterialAsset(src, hasVertexColor: false, modelAsset.Map.Textures);
|
||||
material.name = src.Name;
|
||||
modelAsset.Map.Materials.Add(src, material);
|
||||
modelAsset.Materials.Add(material);
|
||||
}
|
||||
}
|
||||
}
|
||||
// foreach (var src in model.Materials)
|
||||
// {
|
||||
// if (externalObjects.ContainsKey(src.Name))
|
||||
// {
|
||||
// modelAsset.Map.Materials.Add(src, externalObjects[src.Name]);
|
||||
// modelAsset.Materials.Add(externalObjects[src.Name]);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// // TODO: material has VertexColor
|
||||
// var material = RuntimeUnityMaterialBuilder.CreateMaterialAsset(src, hasVertexColor: false, modelAsset.Map.Textures);
|
||||
// material.name = src.Name;
|
||||
// modelAsset.Map.Materials.Add(src, material);
|
||||
// modelAsset.Materials.Add(material);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
static private void CreateMeshAsset(VrmLib.Model model, ModelAsset modelAsset)
|
||||
{
|
||||
for (int i = 0; i < model.MeshGroups.Count; ++i)
|
||||
{
|
||||
var src = model.MeshGroups[i];
|
||||
if (src.Meshes.Count == 1)
|
||||
{
|
||||
// submesh 方式
|
||||
var mesh = new UnityEngine.Mesh();
|
||||
mesh.name = src.Name;
|
||||
mesh.LoadMesh(src.Meshes[0], src.Skin);
|
||||
modelAsset.Map.Meshes.Add(src, mesh);
|
||||
modelAsset.Meshes.Add(mesh);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 頂点バッファの連結が必用
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
// static private void CreateMeshAsset(VrmLib.Model model, ModelAsset modelAsset)
|
||||
// {
|
||||
// for (int i = 0; i < model.MeshGroups.Count; ++i)
|
||||
// {
|
||||
// var src = model.MeshGroups[i];
|
||||
// if (src.Meshes.Count == 1)
|
||||
// {
|
||||
// // submesh 方式
|
||||
// var mesh = new UnityEngine.Mesh();
|
||||
// mesh.name = src.Name;
|
||||
// mesh.LoadMesh(src.Meshes[0], src.Skin);
|
||||
// modelAsset.Map.Meshes.Add(src, mesh);
|
||||
// modelAsset.Meshes.Add(mesh);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// // 頂点バッファの連結が必用
|
||||
// throw new NotImplementedException();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,136 +27,136 @@ namespace UniVRM10
|
||||
var parser = new UniGLTF.GltfParser();
|
||||
parser.ParsePath(ctx.assetPath);
|
||||
|
||||
try
|
||||
{
|
||||
// Create Vrm Model
|
||||
VrmLib.Model model = VrmLoader.CreateVrmModel(parser);
|
||||
if (model == null)
|
||||
{
|
||||
// maybe VRM-0.X
|
||||
return;
|
||||
}
|
||||
Debug.Log($"VrmLoader.CreateVrmModel: {model}");
|
||||
// try
|
||||
// {
|
||||
// // Create Vrm Model
|
||||
// VrmLib.Model model = VrmLoader.CreateVrmModel(parser);
|
||||
// if (model == null)
|
||||
// {
|
||||
// // maybe VRM-0.X
|
||||
// return;
|
||||
// }
|
||||
// Debug.Log($"VrmLoader.CreateVrmModel: {model}");
|
||||
|
||||
// Build Unity Model
|
||||
var assets = EditorUnityBuilder.ToUnityAsset(model, assetPath, this);
|
||||
ComponentBuilder.Build10(model, assets);
|
||||
// // Build Unity Model
|
||||
// var assets = EditorUnityBuilder.ToUnityAsset(model, assetPath, this);
|
||||
// ComponentBuilder.Build10(model, assets);
|
||||
|
||||
// Texture
|
||||
var externalTextures = this.GetExternalUnityObjects<UnityEngine.Texture2D>();
|
||||
foreach (var texture in assets.Textures)
|
||||
{
|
||||
if (texture == null)
|
||||
continue;
|
||||
// // Texture
|
||||
// var externalTextures = this.GetExternalUnityObjects<UnityEngine.Texture2D>();
|
||||
// foreach (var texture in assets.Textures)
|
||||
// {
|
||||
// if (texture == null)
|
||||
// continue;
|
||||
|
||||
if (externalTextures.ContainsValue(texture))
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx.AddObjectToAsset(texture.name, texture);
|
||||
}
|
||||
}
|
||||
// if (externalTextures.ContainsValue(texture))
|
||||
// {
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// ctx.AddObjectToAsset(texture.name, texture);
|
||||
// }
|
||||
// }
|
||||
|
||||
// Material
|
||||
var externalMaterials = this.GetExternalUnityObjects<UnityEngine.Material>();
|
||||
foreach (var material in assets.Materials)
|
||||
{
|
||||
if (material == null)
|
||||
continue;
|
||||
// // Material
|
||||
// var externalMaterials = this.GetExternalUnityObjects<UnityEngine.Material>();
|
||||
// foreach (var material in assets.Materials)
|
||||
// {
|
||||
// if (material == null)
|
||||
// continue;
|
||||
|
||||
if (externalMaterials.ContainsValue(material))
|
||||
{
|
||||
// if (externalMaterials.ContainsValue(material))
|
||||
// {
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx.AddObjectToAsset(material.name, material);
|
||||
}
|
||||
}
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// ctx.AddObjectToAsset(material.name, material);
|
||||
// }
|
||||
// }
|
||||
|
||||
// Mesh
|
||||
foreach (var mesh in assets.Meshes)
|
||||
{
|
||||
ctx.AddObjectToAsset(mesh.name, mesh);
|
||||
}
|
||||
// // Mesh
|
||||
// foreach (var mesh in assets.Meshes)
|
||||
// {
|
||||
// ctx.AddObjectToAsset(mesh.name, mesh);
|
||||
// }
|
||||
|
||||
//// ScriptableObject
|
||||
// avatar
|
||||
ctx.AddObjectToAsset("avatar", assets.HumanoidAvatar);
|
||||
// //// ScriptableObject
|
||||
// // avatar
|
||||
// ctx.AddObjectToAsset("avatar", assets.HumanoidAvatar);
|
||||
|
||||
// meta
|
||||
{
|
||||
var external = this.GetExternalUnityObjects<UniVRM10.VRM10MetaObject>().FirstOrDefault();
|
||||
if (external.Value != null)
|
||||
{
|
||||
var controller = assets.Root.GetComponent<VRM10Controller>();
|
||||
if (controller != null)
|
||||
{
|
||||
controller.Meta = external.Value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var meta = assets.ScriptableObjects
|
||||
.FirstOrDefault(x => x.GetType() == typeof(UniVRM10.VRM10MetaObject)) as UniVRM10.VRM10MetaObject;
|
||||
if (meta != null)
|
||||
{
|
||||
meta.name = "meta";
|
||||
ctx.AddObjectToAsset(meta.name, meta);
|
||||
}
|
||||
}
|
||||
}
|
||||
// // meta
|
||||
// {
|
||||
// var external = this.GetExternalUnityObjects<UniVRM10.VRM10MetaObject>().FirstOrDefault();
|
||||
// if (external.Value != null)
|
||||
// {
|
||||
// var controller = assets.Root.GetComponent<VRM10Controller>();
|
||||
// if (controller != null)
|
||||
// {
|
||||
// controller.Meta = external.Value;
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// var meta = assets.ScriptableObjects
|
||||
// .FirstOrDefault(x => x.GetType() == typeof(UniVRM10.VRM10MetaObject)) as UniVRM10.VRM10MetaObject;
|
||||
// if (meta != null)
|
||||
// {
|
||||
// meta.name = "meta";
|
||||
// ctx.AddObjectToAsset(meta.name, meta);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// expression
|
||||
{
|
||||
var external = this.GetExternalUnityObjects<UniVRM10.VRM10Expression>();
|
||||
if (external.Any())
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
var expression = assets.ScriptableObjects
|
||||
.Where(x => x.GetType() == typeof(UniVRM10.VRM10Expression))
|
||||
.Select(x => x as UniVRM10.VRM10Expression);
|
||||
foreach (var clip in expression)
|
||||
{
|
||||
clip.name = clip.ExpressionName;
|
||||
ctx.AddObjectToAsset(clip.ExpressionName, clip);
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
var external = this.GetExternalUnityObjects<UniVRM10.VRM10ExpressionAvatar>().FirstOrDefault();
|
||||
if (external.Value != null)
|
||||
{
|
||||
var controller = assets.Root.GetComponent<VRM10Controller>();
|
||||
if (controller != null)
|
||||
{
|
||||
controller.Expression.ExpressionAvatar = external.Value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var expressionAvatar = assets.ScriptableObjects
|
||||
.FirstOrDefault(x => x.GetType() == typeof(UniVRM10.VRM10ExpressionAvatar)) as UniVRM10.VRM10ExpressionAvatar;
|
||||
if (expressionAvatar != null)
|
||||
{
|
||||
expressionAvatar.name = "expressionAvatar";
|
||||
ctx.AddObjectToAsset(expressionAvatar.name, expressionAvatar);
|
||||
}
|
||||
}
|
||||
}
|
||||
// // expression
|
||||
// {
|
||||
// var external = this.GetExternalUnityObjects<UniVRM10.VRM10Expression>();
|
||||
// if (external.Any())
|
||||
// {
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// var expression = assets.ScriptableObjects
|
||||
// .Where(x => x.GetType() == typeof(UniVRM10.VRM10Expression))
|
||||
// .Select(x => x as UniVRM10.VRM10Expression);
|
||||
// foreach (var clip in expression)
|
||||
// {
|
||||
// clip.name = clip.ExpressionName;
|
||||
// ctx.AddObjectToAsset(clip.ExpressionName, clip);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// {
|
||||
// var external = this.GetExternalUnityObjects<UniVRM10.VRM10ExpressionAvatar>().FirstOrDefault();
|
||||
// if (external.Value != null)
|
||||
// {
|
||||
// var controller = assets.Root.GetComponent<VRM10Controller>();
|
||||
// if (controller != null)
|
||||
// {
|
||||
// controller.Expression.ExpressionAvatar = external.Value;
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// var expressionAvatar = assets.ScriptableObjects
|
||||
// .FirstOrDefault(x => x.GetType() == typeof(UniVRM10.VRM10ExpressionAvatar)) as UniVRM10.VRM10ExpressionAvatar;
|
||||
// if (expressionAvatar != null)
|
||||
// {
|
||||
// expressionAvatar.name = "expressionAvatar";
|
||||
// ctx.AddObjectToAsset(expressionAvatar.name, expressionAvatar);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// Root
|
||||
ctx.AddObjectToAsset(assets.Root.name, assets.Root);
|
||||
ctx.SetMainObject(assets.Root);
|
||||
// // Root
|
||||
// ctx.AddObjectToAsset(assets.Root.name, assets.Root);
|
||||
// ctx.SetMainObject(assets.Root);
|
||||
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Debug.LogError(ex);
|
||||
}
|
||||
// }
|
||||
// catch (System.Exception ex)
|
||||
// {
|
||||
// Debug.LogError(ex);
|
||||
// }
|
||||
}
|
||||
|
||||
public void ExtractTextures()
|
||||
|
||||
@@ -3,31 +3,24 @@ using System.IO;
|
||||
using UnityEngine;
|
||||
using VrmLib;
|
||||
using UniVRM10;
|
||||
using UniGLTF;
|
||||
|
||||
public class Sample : MonoBehaviour
|
||||
{
|
||||
[SerializeField]
|
||||
string m_vrmPath = "Tests/Models/Alicia_vrm-0.51/AliciaSolid_vrm-0.51.vrm";
|
||||
|
||||
static UniVRM10.ModelAsset Import(byte[] bytes, FileInfo path)
|
||||
static GameObject Import(byte[] bytes, FileInfo path)
|
||||
{
|
||||
var parser = new UniGLTF.GltfParser();
|
||||
var parser = new GltfParser();
|
||||
parser.Parse(path.FullName, bytes);
|
||||
|
||||
var model = UniVRM10.VrmLoader.CreateVrmModel(parser);
|
||||
|
||||
// UniVRM-0.XXのコンポーネントを構築する
|
||||
var assets = UniVRM10.RuntimeUnityBuilder.ToUnityAsset(model, showMesh: false);
|
||||
|
||||
// showRenderer = false のときに後で表示する例
|
||||
foreach (var renderer in assets.Renderers)
|
||||
using (var loader = new RuntimeUnityBuilder(parser))
|
||||
{
|
||||
renderer.enabled = true;
|
||||
loader.Load();
|
||||
loader.ShowMeshes();
|
||||
return loader.DisposeOnGameObjectDestroyed().gameObject;
|
||||
}
|
||||
|
||||
UniVRM10.ComponentBuilder.Build10(model, assets);
|
||||
|
||||
return assets;
|
||||
}
|
||||
|
||||
// Start is called before the first frame update
|
||||
@@ -38,17 +31,17 @@ public class Sample : MonoBehaviour
|
||||
|
||||
// Export 1.0
|
||||
var exporter = new UniVRM10.RuntimeVrmConverter();
|
||||
var model = exporter.ToModelFrom10(vrm0x.Root);
|
||||
var model = exporter.ToModelFrom10(vrm0x);
|
||||
// 右手系に変換
|
||||
model.ConvertCoordinate(VrmLib.Coordinates.Vrm1);
|
||||
var exportedBytes = model.ToGlb();
|
||||
|
||||
// Import 1.0
|
||||
var vrm10 = Import(exportedBytes, src);
|
||||
var pos = vrm10.Root.transform.position;
|
||||
var pos = vrm10.transform.position;
|
||||
pos.x += 1.5f;
|
||||
vrm10.Root.transform.position = pos;
|
||||
vrm10.Root.name = vrm10.Root.name + "_Imported_v1_0";
|
||||
vrm10.transform.position = pos;
|
||||
vrm10.name = vrm10.name + "_Imported_v1_0";
|
||||
|
||||
// write
|
||||
var path = Path.GetFullPath("vrm10.vrm");
|
||||
|
||||
@@ -1,66 +1,61 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using MeshUtility;
|
||||
using System.Threading.Tasks;
|
||||
using UniGLTF;
|
||||
using UnityEngine;
|
||||
using VrmLib;
|
||||
|
||||
|
||||
namespace UniVRM10
|
||||
{
|
||||
/// <summary>
|
||||
/// VrmLib.Model から UnityPrefab を構築する
|
||||
/// </summary>
|
||||
public static class RuntimeUnityBuilder
|
||||
public class RuntimeUnityBuilder : UniGLTF.ImporterContext
|
||||
{
|
||||
readonly Model m_model;
|
||||
|
||||
/// <summary>
|
||||
/// モデル(Transform + Renderer)を構築する。
|
||||
/// <summary>
|
||||
public static ModelAsset ToUnityAsset(VrmLib.Model model, bool showMesh = true)
|
||||
/// VrmLib.Model の オブジェクトと UnityEngine.Object のマッピングを記録する
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
readonly ModelAsset m_asset = new ModelAsset();
|
||||
|
||||
public ModelAsset Asset => m_asset;
|
||||
|
||||
public RuntimeUnityBuilder(UniGLTF.GltfParser parser, IEnumerable<(string, UnityEngine.Object)> externalObjectMap = null) : base(parser, externalObjectMap)
|
||||
{
|
||||
var modelAsset = new ModelAsset();
|
||||
m_model = VrmLoader.CreateVrmModel(parser);
|
||||
}
|
||||
|
||||
// texture
|
||||
for (int i = 0; i < model.Textures.Count; ++i)
|
||||
/// <summary>
|
||||
/// VrmLib.Model から 構築する
|
||||
/// </summary>
|
||||
/// <param name="MeasureTime"></param>
|
||||
/// <returns></returns>
|
||||
protected override async Task LoadGeometryAsync(Func<string, IDisposable> MeasureTime)
|
||||
{
|
||||
// fill assets
|
||||
for (int i = 0; i < m_model.Materials.Count; ++i)
|
||||
{
|
||||
var src = model.Textures[i];
|
||||
var name = !string.IsNullOrEmpty(src.Name)
|
||||
? src.Name
|
||||
: string.Format("{0}_img{1}", model.Root.Name, i);
|
||||
if (src is VrmLib.ImageTexture imageTexture)
|
||||
{
|
||||
var texture = CreateTexture(imageTexture);
|
||||
texture.name = name;
|
||||
modelAsset.Map.Textures.Add(src, texture);
|
||||
modelAsset.Textures.Add(texture);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"{name} not ImageTexture");
|
||||
}
|
||||
}
|
||||
|
||||
// material
|
||||
foreach (var src in model.Materials)
|
||||
{
|
||||
// TODO: material has VertexColor
|
||||
var material = RuntimeUnityMaterialBuilder.CreateMaterialAsset(src, hasVertexColor: false, modelAsset.Map.Textures);
|
||||
material.name = src.Name;
|
||||
modelAsset.Map.Materials.Add(src, material);
|
||||
modelAsset.Materials.Add(material);
|
||||
var src = m_model.Materials[i];
|
||||
var dst = MaterialFactory.Materials[i].Asset;
|
||||
m_asset.Map.Materials.Add(src, dst);
|
||||
}
|
||||
|
||||
// mesh
|
||||
for (int i = 0; i < model.MeshGroups.Count; ++i)
|
||||
for (int i = 0; i < m_model.MeshGroups.Count; ++i)
|
||||
{
|
||||
var src = model.MeshGroups[i];
|
||||
var src = m_model.MeshGroups[i];
|
||||
if (src.Meshes.Count == 1)
|
||||
{
|
||||
// submesh 方式
|
||||
var mesh = new UnityEngine.Mesh();
|
||||
mesh.name = src.Name;
|
||||
mesh.LoadMesh(src.Meshes[0], src.Skin);
|
||||
modelAsset.Map.Meshes.Add(src, mesh);
|
||||
modelAsset.Meshes.Add(mesh);
|
||||
m_asset.Map.Meshes.Add(src, mesh);
|
||||
m_asset.Meshes.Add(mesh);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -70,11 +65,11 @@ namespace UniVRM10
|
||||
}
|
||||
|
||||
// node: recursive
|
||||
CreateNodes(model.Root, null, modelAsset.Map.Nodes);
|
||||
modelAsset.Root = modelAsset.Map.Nodes[model.Root];
|
||||
CreateNodes(m_model.Root, null, m_asset.Map.Nodes);
|
||||
m_asset.Root = m_asset.Map.Nodes[m_model.Root];
|
||||
|
||||
// renderer
|
||||
var map = modelAsset.Map;
|
||||
var map = m_asset.Map;
|
||||
foreach (var (node, go) in map.Nodes)
|
||||
{
|
||||
if (node.MeshGroup is null)
|
||||
@@ -88,26 +83,30 @@ namespace UniVRM10
|
||||
}
|
||||
|
||||
var renderer = CreateRenderer(node, go, map);
|
||||
if (!showMesh)
|
||||
{
|
||||
renderer.enabled = false;
|
||||
}
|
||||
map.Renderers.Add(node, renderer);
|
||||
modelAsset.Renderers.Add(renderer);
|
||||
m_asset.Renderers.Add(renderer);
|
||||
}
|
||||
|
||||
var humanoid = modelAsset.Root.AddComponent<MeshUtility.Humanoid>();
|
||||
humanoid.AssignBones(map.Nodes.Select(x => (x.Key.HumanoidBone.GetValueOrDefault().ToUnity(), x.Value.transform)));
|
||||
modelAsset.HumanoidAvatar = humanoid.CreateAvatar();
|
||||
modelAsset.HumanoidAvatar.name = "VRM";
|
||||
var humanoid = m_asset.Root.AddComponent<MeshUtility.Humanoid>();
|
||||
humanoid.AssignBones(map.Nodes.Select(x => (ToUnity(x.Key.HumanoidBone.GetValueOrDefault()), x.Value.transform)));
|
||||
m_asset.HumanoidAvatar = humanoid.CreateAvatar();
|
||||
m_asset.HumanoidAvatar.name = "VRM";
|
||||
|
||||
var animator = modelAsset.Root.AddComponent<Animator>();
|
||||
animator.avatar = modelAsset.HumanoidAvatar;
|
||||
|
||||
return modelAsset;
|
||||
var animator = m_asset.Root.AddComponent<Animator>();
|
||||
animator.avatar = m_asset.HumanoidAvatar;
|
||||
}
|
||||
|
||||
public static HumanBodyBones ToUnity(this VrmLib.HumanoidBones bone)
|
||||
protected override async Task OnLoadModel(IAwaitCaller awaitCaller, Func<string, IDisposable> MeasureTime)
|
||||
{
|
||||
Root.name = "VRM1";
|
||||
|
||||
// UniVRM10.ComponentBuilder.Build10(m_model, m_assets);
|
||||
|
||||
// var model = VrmLoader.CreateVrmModel(parser);
|
||||
// model.RemoveSecondary();
|
||||
}
|
||||
|
||||
public static HumanBodyBones ToUnity(VrmLib.HumanoidBones bone)
|
||||
{
|
||||
if (bone == VrmLib.HumanoidBones.unknown)
|
||||
{
|
||||
@@ -116,65 +115,6 @@ namespace UniVRM10
|
||||
return VrmLib.EnumUtil.Cast<HumanBodyBones>(bone);
|
||||
}
|
||||
|
||||
private static RenderTextureReadWrite GetRenderTextureReadWrite(VrmLib.Texture.ColorSpaceTypes type)
|
||||
{
|
||||
return (type == VrmLib.Texture.ColorSpaceTypes.Linear) ? RenderTextureReadWrite.Linear : RenderTextureReadWrite.sRGB;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 画像のバイト列からテクスチャを作成する
|
||||
/// <summary>
|
||||
public static Texture2D CreateTexture(VrmLib.ImageTexture imageTexture)
|
||||
{
|
||||
Texture2D dstTexture = null;
|
||||
UnityEngine.Material convertMaterial = null;
|
||||
var texture = new Texture2D(2, 2, TextureFormat.ARGB32, false, imageTexture.ColorSpace == VrmLib.Texture.ColorSpaceTypes.Linear);
|
||||
texture.LoadImage(imageTexture.Image.Bytes.ToArray());
|
||||
|
||||
// Convert Texture Gltf to Unity
|
||||
if (imageTexture.TextureType == VrmLib.Texture.TextureTypes.NormalMap)
|
||||
{
|
||||
convertMaterial = TextureConvertMaterial.GetNormalMapConvertGltfToUnity();
|
||||
dstTexture = UnityTextureUtil.CopyTexture(
|
||||
texture,
|
||||
GetRenderTextureReadWrite(imageTexture.ColorSpace),
|
||||
convertMaterial);
|
||||
}
|
||||
else if (imageTexture.TextureType == VrmLib.Texture.TextureTypes.MetallicRoughness)
|
||||
{
|
||||
var metallicRoughnessImage = imageTexture as VrmLib.MetallicRoughnessImageTexture;
|
||||
convertMaterial = TextureConvertMaterial.GetMetallicRoughnessGltfToUnity(metallicRoughnessImage.RoughnessFactor);
|
||||
dstTexture = UnityTextureUtil.CopyTexture(
|
||||
texture,
|
||||
GetRenderTextureReadWrite(imageTexture.ColorSpace),
|
||||
convertMaterial);
|
||||
}
|
||||
else if (imageTexture.TextureType == VrmLib.Texture.TextureTypes.Occlusion)
|
||||
{
|
||||
convertMaterial = TextureConvertMaterial.GetOcclusionGltfToUnity();
|
||||
dstTexture = UnityTextureUtil.CopyTexture(
|
||||
texture,
|
||||
GetRenderTextureReadWrite(imageTexture.ColorSpace),
|
||||
convertMaterial);
|
||||
}
|
||||
|
||||
if (dstTexture != null)
|
||||
{
|
||||
if (texture != null)
|
||||
{
|
||||
UnityEngine.Object.DestroyImmediate(texture);
|
||||
}
|
||||
texture = dstTexture;
|
||||
}
|
||||
|
||||
if (convertMaterial != null)
|
||||
{
|
||||
UnityEngine.Object.DestroyImmediate(convertMaterial);
|
||||
}
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ヒエラルキーを再帰的に構築する
|
||||
/// <summary>
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
"MToon",
|
||||
"MeshUtility",
|
||||
"MeshUtility.Editor",
|
||||
"UniGLTF"
|
||||
"UniGLTF",
|
||||
"VRMShaders"
|
||||
],
|
||||
"optionalUnityReferences": [],
|
||||
"includePlatforms": [],
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using UniGLTF;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using UniVRM10;
|
||||
@@ -46,18 +47,18 @@ namespace UniVRM10.Test
|
||||
var parser = new UniGLTF.GltfParser();
|
||||
parser.Parse("tmp.vrm", bytes);
|
||||
|
||||
var model = VrmLoader.CreateVrmModel(parser);
|
||||
model.RemoveSecondary();
|
||||
|
||||
return ToUnity(model);
|
||||
return ToUnity(parser);
|
||||
}
|
||||
|
||||
private ModelAsset ToUnity(Model model)
|
||||
private ModelAsset ToUnity(GltfParser parser)
|
||||
{
|
||||
// Model => Unity
|
||||
var assets = RuntimeUnityBuilder.ToUnityAsset(model);
|
||||
UniVRM10.ComponentBuilder.Build10(model, assets);
|
||||
return assets;
|
||||
using (var loader = new RuntimeUnityBuilder(parser))
|
||||
{
|
||||
loader.Load();
|
||||
loader.DisposeOnGameObjectDestroyed();
|
||||
return loader.Asset;
|
||||
}
|
||||
}
|
||||
|
||||
private Model ToVrmModel(GameObject root)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using NUnit.Framework;
|
||||
using UniGLTF;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
|
||||
@@ -12,18 +13,25 @@ namespace UniVRM10.Test
|
||||
{
|
||||
var bytes = MigrationVrm.Migrate(File.ReadAllBytes(path));
|
||||
|
||||
var parser = new UniGLTF.GltfParser();
|
||||
var parser = new GltfParser();
|
||||
parser.Parse("migrated", bytes);
|
||||
|
||||
var model = UniVRM10.VrmLoader.CreateVrmModel(parser);
|
||||
return model;
|
||||
}
|
||||
|
||||
ModelAsset BuildGameObject(VrmLib.Model model, bool showMesh)
|
||||
GameObject BuildGameObject(GltfParser parser, bool showMesh)
|
||||
{
|
||||
var assets = RuntimeUnityBuilder.ToUnityAsset(model, showMesh);
|
||||
UniVRM10.ComponentBuilder.Build10(model, assets);
|
||||
return assets;
|
||||
using (var loader = new RuntimeUnityBuilder(parser))
|
||||
{
|
||||
loader.Load();
|
||||
if (showMesh)
|
||||
{
|
||||
loader.ShowMeshes();
|
||||
}
|
||||
loader.EnableUpdateWhenOffscreen();
|
||||
return loader.DisposeOnGameObjectDestroyed().gameObject;
|
||||
}
|
||||
}
|
||||
|
||||
VrmLib.Model ToModel(UnityEngine.GameObject target)
|
||||
@@ -47,27 +55,14 @@ namespace UniVRM10.Test
|
||||
var path = "Tests/Models/Alicia_vrm-0.51/AliciaSolid_vrm-0.51.vrm";
|
||||
Debug.Log($"load: {path}");
|
||||
|
||||
// import
|
||||
var srcModel = ReadModel(path);
|
||||
Debug.Log(srcModel);
|
||||
var parser = new GltfParser();
|
||||
parser.ParsePath(path);
|
||||
|
||||
var asset = BuildGameObject(srcModel, false);
|
||||
var asset = BuildGameObject(parser, true);
|
||||
Debug.Log(asset);
|
||||
|
||||
// renderer setting
|
||||
foreach (var render in asset.Renderers)
|
||||
{
|
||||
// show when RuntimeUnityBuilder.ToUnity(showMesh = false)
|
||||
render.enabled = true;
|
||||
// avoid culling
|
||||
if (render is SkinnedMeshRenderer skinned)
|
||||
{
|
||||
skinned.updateWhenOffscreen = true;
|
||||
}
|
||||
}
|
||||
|
||||
// export
|
||||
var dstModel = ToModel(asset.Root);
|
||||
var dstModel = ToModel(asset);
|
||||
Debug.Log(dstModel);
|
||||
|
||||
var vrmBytes = ToVrm10(dstModel);
|
||||
|
||||
Reference in New Issue
Block a user