WIP UniGLTF with VrmLib.Model

This commit is contained in:
ousttrue
2021-03-29 20:05:57 +09:00
parent 8629f4df5c
commit fec118d788
9 changed files with 380 additions and 446 deletions

View File

@@ -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()

View File

@@ -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);
}
}
}

View File

@@ -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();
// }
// }
// }
}
}

View File

@@ -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()

View File

@@ -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");

View File

@@ -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>

View File

@@ -6,7 +6,8 @@
"MToon",
"MeshUtility",
"MeshUtility.Editor",
"UniGLTF"
"UniGLTF",
"VRMShaders"
],
"optionalUnityReferences": [],
"includePlatforms": [],

View File

@@ -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)

View File

@@ -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);