diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs index 5f7d6422b..d5a7beccf 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs @@ -3,9 +3,9 @@ using System.Linq; using System.Collections.Generic; using UnityEngine; using System.Threading.Tasks; -using System.Text; using VRMShaders; + namespace UniGLTF { /// @@ -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 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() diff --git a/Assets/VRM10.Samples/Runtime/ViewerUI.cs b/Assets/VRM10.Samples/Runtime/ViewerUI.cs index 3fce9ec77..cf2e6ce57 100644 --- a/Assets/VRM10.Samples/Runtime/ViewerUI.cs +++ b/Assets/VRM10.Samples/Runtime/ViewerUI.cs @@ -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(); - - 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(); - m_loaded.Source = m_src; - m_loaded.SourceType = HumanPoseTransfer.HumanPoseTransferSourceType.HumanPoseTransfer; - m_lipSync = go.AddComponent(); - m_blink = go.AddComponent(); + 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(); + m_loaded.Source = m_src; + m_loaded.SourceType = HumanPoseTransfer.HumanPoseTransferSourceType.HumanPoseTransfer; + + m_lipSync = go.AddComponent(); + m_blink = go.AddComponent(); + + m_controller.LookAt.Gaze = m_target.transform; + } } var animation = go.GetComponent(); @@ -402,7 +402,6 @@ namespace UniVRM10.Samples { animation.Play(animation.clip.name); } - } } diff --git a/Assets/VRM10/Editor/EditorUnityBuilder.cs b/Assets/VRM10/Editor/EditorUnityBuilder.cs index 948851801..8d7413577 100644 --- a/Assets/VRM10/Editor/EditorUnityBuilder.cs +++ b/Assets/VRM10/Editor/EditorUnityBuilder.cs @@ -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(); - 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(); + // 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.avatar = modelAsset.HumanoidAvatar; - } + // var animator = modelAsset.Root.AddComponent(); + // animator.avatar = modelAsset.HumanoidAvatar; + // } - return modelAsset; - } + // return modelAsset; + // } - static private void CreateTextureAsset(VrmLib.Model model, ModelAsset modelAsset, IExternalUnityObject scriptedImporter) - { - var externalObjects = scriptedImporter.GetExternalUnityObjects(); + // static private void CreateTextureAsset(VrmLib.Model model, ModelAsset modelAsset, IExternalUnityObject scriptedImporter) + // { + // var externalObjects = scriptedImporter.GetExternalUnityObjects(); - // 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(); + // static private void CreateMaterialAsset(VrmLib.Model model, ModelAsset modelAsset, IExternalUnityObject scriptedImporter) + // { + // var externalObjects = scriptedImporter.GetExternalUnityObjects(); - 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(); + // } + // } + // } } } diff --git a/Assets/VRM10/Editor/ScriptedImporter/VrmScriptedImporter.cs b/Assets/VRM10/Editor/ScriptedImporter/VrmScriptedImporter.cs index 81d3a1c33..3665838f8 100644 --- a/Assets/VRM10/Editor/ScriptedImporter/VrmScriptedImporter.cs +++ b/Assets/VRM10/Editor/ScriptedImporter/VrmScriptedImporter.cs @@ -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(); - foreach (var texture in assets.Textures) - { - if (texture == null) - continue; + // // Texture + // var externalTextures = this.GetExternalUnityObjects(); + // 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(); - foreach (var material in assets.Materials) - { - if (material == null) - continue; + // // Material + // var externalMaterials = this.GetExternalUnityObjects(); + // 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().FirstOrDefault(); - if (external.Value != null) - { - var controller = assets.Root.GetComponent(); - 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().FirstOrDefault(); + // if (external.Value != null) + // { + // var controller = assets.Root.GetComponent(); + // 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(); - 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().FirstOrDefault(); - if (external.Value != null) - { - var controller = assets.Root.GetComponent(); - 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(); + // 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().FirstOrDefault(); + // if (external.Value != null) + // { + // var controller = assets.Root.GetComponent(); + // 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() diff --git a/Assets/VRM10/Runtime/Scenes/Sample.cs b/Assets/VRM10/Runtime/Scenes/Sample.cs index 36a5ae82b..9bc304bb6 100644 --- a/Assets/VRM10/Runtime/Scenes/Sample.cs +++ b/Assets/VRM10/Runtime/Scenes/Sample.cs @@ -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"); diff --git a/Assets/VRM10/Runtime/UnityBuilder/RuntimeUnityBuilder.cs b/Assets/VRM10/Runtime/UnityBuilder/RuntimeUnityBuilder.cs index 163f56d17..37ccab91c 100644 --- a/Assets/VRM10/Runtime/UnityBuilder/RuntimeUnityBuilder.cs +++ b/Assets/VRM10/Runtime/UnityBuilder/RuntimeUnityBuilder.cs @@ -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 { /// /// VrmLib.Model から UnityPrefab を構築する /// - public static class RuntimeUnityBuilder + public class RuntimeUnityBuilder : UniGLTF.ImporterContext { + readonly Model m_model; + /// - /// モデル(Transform + Renderer)を構築する。 - /// - public static ModelAsset ToUnityAsset(VrmLib.Model model, bool showMesh = true) + /// VrmLib.Model の オブジェクトと UnityEngine.Object のマッピングを記録する + /// + /// + 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) + /// + /// VrmLib.Model から 構築する + /// + /// + /// + protected override async Task LoadGeometryAsync(Func 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(); - 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(); + 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.avatar = modelAsset.HumanoidAvatar; - - return modelAsset; + var animator = m_asset.Root.AddComponent(); + animator.avatar = m_asset.HumanoidAvatar; } - public static HumanBodyBones ToUnity(this VrmLib.HumanoidBones bone) + protected override async Task OnLoadModel(IAwaitCaller awaitCaller, Func 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(bone); } - private static RenderTextureReadWrite GetRenderTextureReadWrite(VrmLib.Texture.ColorSpaceTypes type) - { - return (type == VrmLib.Texture.ColorSpaceTypes.Linear) ? RenderTextureReadWrite.Linear : RenderTextureReadWrite.sRGB; - } - - /// - /// 画像のバイト列からテクスチャを作成する - /// - 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; - } - /// /// ヒエラルキーを再帰的に構築する /// diff --git a/Assets/VRM10/Runtime/VRM10.asmdef b/Assets/VRM10/Runtime/VRM10.asmdef index 8bec55972..de687fb35 100644 --- a/Assets/VRM10/Runtime/VRM10.asmdef +++ b/Assets/VRM10/Runtime/VRM10.asmdef @@ -6,7 +6,8 @@ "MToon", "MeshUtility", "MeshUtility.Editor", - "UniGLTF" + "UniGLTF", + "VRMShaders" ], "optionalUnityReferences": [], "includePlatforms": [], diff --git a/Assets/VRM10/Tests.PlayMode/MaterialTests.cs b/Assets/VRM10/Tests.PlayMode/MaterialTests.cs index ded4007e0..c97a9db33 100644 --- a/Assets/VRM10/Tests.PlayMode/MaterialTests.cs +++ b/Assets/VRM10/Tests.PlayMode/MaterialTests.cs @@ -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) diff --git a/Assets/VRM10/Tests/ApiSampleTests.cs b/Assets/VRM10/Tests/ApiSampleTests.cs index a624f87c9..94db7e1fd 100644 --- a/Assets/VRM10/Tests/ApiSampleTests.cs +++ b/Assets/VRM10/Tests/ApiSampleTests.cs @@ -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);