/// <summary> /// 非同期でByte配列からVRMモデルを読み込む /// </summary> /// <param name="vrmByteArray"></param> /// <returns></returns> public async Task <GameObject> LoadVrmModelFromByteArrayAsync(byte[] vrmByteArray) { #if UNIVRM_LEGACY_IMPORTER await InitializeVrmContextFromByteArrayAsync(vrmByteArray); // 非同期処理(Task)で読み込みます await currentContext.LoadAsyncTask(); // 読込が完了するとcontext.RootにモデルのGameObjectが入っています var root = currentContext.Root; return(root); #elif UNIVRM_0_68_IMPORTER var parser = new GltfParser(); await Task.Run(() => { parser.ParseGlb(vrmByteArray); }); currentContext = new VRMImporterContext(parser); await currentContext.LoadAsync(); return(currentContext.Root); #else return(null); #endif }
/// <summary> /// 同期でByte配列からVRMモデルを読み込む /// </summary> /// <param name="vrmByteArray"></param> /// <returns></returns> public GameObject LoadVrmModelFromByteArray(byte[] vrmByteArray) { #if UNIVRM_LEGACY_IMPORTER InitializeVrmContextFromByteArray(vrmByteArray); // 同期処理で読み込みます currentContext.Load(); // 読込が完了するとcontext.RootにモデルのGameObjectが入っています var root = currentContext.Root; return(root); #elif UNIVRM_0_68_IMPORTER var parser = new GltfParser(); parser.ParseGlb(vrmByteArray); currentContext = new VRMImporterContext(parser); currentContext.Load(); return(currentContext.Root); #elif UNIVRM_0_77_IMPORTER var parser = new GlbLowLevelParser(string.Empty, vrmByteArray); var data = parser.Parse(); currentContext = new VRMImporterContext(data); currentInstance = currentContext.Load(); return(currentInstance.Root); #else return(null); #endif }
/// <summary> /// SubAssetを外部ファイルに展開する /// </summary> public static void Extract(ScriptedImporter importer, GltfParser parser) { if (string.IsNullOrEmpty(importer.assetPath)) { return; } // meta { var path = GetAndCreateFolder(importer.assetPath, ".vrm1.Meta"); foreach (var(key, asset) in importer.GetSubAssets <VRM10MetaObject>(importer.assetPath)) { asset.ExtractSubAsset($"{path}/{asset.name}.asset", false); } } { // expressions var path = GetAndCreateFolder(importer.assetPath, ".vrm1.Expressions"); foreach (var(key, asset) in importer.GetSubAssets <VRM10Expression>(importer.assetPath)) { asset.ExtractSubAsset($"{path}/{asset.name}.asset", false); } } AssetDatabase.ImportAsset(importer.assetPath, ImportAssetOptions.ForceUpdate); }
public static void OnGUI(ScriptedImporter importer, GltfParser parser, UniGLTF.Extensions.VRMC_vrm.VRMC_vrm vrm) { var hasExternal = importer.GetExternalObjectMap().Any(x => x.Value is VRM10MetaObject || x.Value is VRM10ExpressionAvatar || x.Value is VRM10Expression); using (new TmpGuiEnable(!hasExternal)) { if (GUILayout.Button("Extract Meta And Expressions ...")) { Extract(importer, parser); } } // meta importer.DrawRemapGUI <VRM10MetaObject>(new SubAssetKey[] { VRM10MetaObject.SubAssetKey }); // expression avatar importer.DrawRemapGUI <VRM10ExpressionAvatar>(new SubAssetKey[] { VRM10ExpressionAvatar.SubAssetKey }); // expressions importer.DrawRemapGUI <VRM10Expression>(vrm.Expressions.Select(x => CreateKey(x).SubAssetKey)); if (GUILayout.Button("Clear")) { importer.ClearExternalObjects <VRM10MetaObject>(); importer.ClearExternalObjects <VRM10ExpressionAvatar>(); importer.ClearExternalObjects <VRM10Expression>(); } }
public void VRMLookAtTest() { var parser = new GltfParser(); parser.ParsePath(AliciaPath); byte[] bytes = default; using (var loader = new VRMImporterContext(parser)) { loader.Load(); loader.ShowMeshes(); var go = loader.Root; var fp = go.GetComponent <VRMFirstPerson>(); GameObject.DestroyImmediate(go.GetComponent <VRMLookAtBoneApplyer>()); go.AddComponent <VRMLookAtBlendShapeApplyer>(); bytes = VRMEditorExporter.Export(go, null, new VRMExportSettings { PoseFreeze = true, }); } var parser2 = new GltfParser(); parser2.Parse(AliciaPath, bytes); var loader2 = new VRMImporterContext(parser2); Assert.AreEqual(LookAtType.BlendShape, loader2.VRM.firstPerson.lookAtType); }
/// <summary> /// 非同期でByte配列からVRMImporterContextの初期化をします /// </summary> /// <param name="vrmByteArray"></param> public async Task InitializeVrmContextFromByteArrayAsync(byte[] vrmByteArray) { #if UNIVRM_LEGACY_IMPORTER // VRMImporterContextがVRMを読み込む機能を提供します currentContext = new VRMImporterContext(); // GLB形式でJSONを取得しParseします await Task.Run(() => currentContext.ParseGlb(vrmByteArray)); #elif UNIVRM_0_68_IMPORTER var parser = new GltfParser(); await Task.Run(() => parser.ParseGlb(vrmByteArray)); currentContext = new VRMImporterContext(parser); #elif UNIVRM_0_77_IMPORTER var parser = new GlbLowLevelParser(string.Empty, vrmByteArray); GltfData data = null; await Task.Run(() => { data = parser.Parse(); }); currentContext = new VRMImporterContext(data); currentInstance = null; #else #endif }
async void OnLoadClicked() { #if UNITY_STANDALONE_WIN var path = FileDialogForWindows.FileDialog("open VRM", ".vrm"); #elif UNITY_EDITOR var path = UnityEditor.EditorUtility.OpenFilePanel("Open VRM", "", "vrm"); #else var path = Application.dataPath + "/default.vrm"; #endif if (string.IsNullOrEmpty(path)) { return; } var bytes = File.ReadAllBytes(path); // なんらかの方法でByte列を得た // GLB形式でJSONを取得しParseします var parser = new GltfParser(); parser.ParseGlb(bytes); using (var context = new VRMImporterContext(parser)) { // metaを取得(todo: thumbnailテクスチャのロード) var meta = await context.ReadMetaAsync(); Debug.LogFormat("meta: title:{0}", meta.Title); // ParseしたJSONをシーンオブジェクトに変換していく await context.LoadAsync(); OnLoaded(context); } }
public void Sample() { var path = "Tests/Models/Alicia_vrm-0.51/AliciaSolid_vrm-0.51.vrm"; Debug.Log($"load: {path}"); var migrated = MigrationVrm.Migrate(File.ReadAllBytes(path)); var parser = new GltfParser(); parser.Parse(path, migrated); var asset = BuildGameObject(parser, true); Debug.Log(asset); // export var dstModel = ToModel(asset); Debug.Log(dstModel); var vrmBytes = ToVrm10(dstModel); Debug.Log($"export {vrmBytes.Length} bytes"); }
/// <summary> /// メタが不要な場合のローダー /// </summary> async void LoadVRMClicked_without_meta() { #if UNITY_STANDALONE_WIN var path = FileDialogForWindows.FileDialog("open VRM", ".vrm"); #elif UNITY_EDITOR var path = UnityEditor.EditorUtility.OpenFilePanel("Open VRM", "", "vrm"); #else var path = Application.dataPath + "/default.vrm"; #endif if (string.IsNullOrEmpty(path)) { return; } var bytes = File.ReadAllBytes(path); // なんらかの方法でByte列を得た // GLB形式でJSONを取得しParseします var parser = new GltfParser(); parser.ParseGlb(bytes); var context = new VRMImporterContext(parser); if (m_loadAsync) { await context.LoadAsync(); } else { context.Load(); } OnLoaded(context); }
public void SerializerCompare() { // Aliciaを古いデシリアライザでロードする var path = AliciaPath; var parser = new GltfParser(); parser.ParseGlb(File.ReadAllBytes(path)); using (var context = new VRMImporterContext(parser)) { var oldJson = context.GLTF.ToJson().ParseAsJson().ToString(" "); // 生成シリアライザでJSON化する var f = new JsonFormatter(); GltfSerializer.Serialize(f, context.GLTF); var parsed = f.ToString().ParseAsJson(); var newJson = parsed.ToString(" "); // File.WriteAllText("old.json", oldJson); // File.WriteAllText("new.json", newJson); // 比較 Assert.AreEqual(oldJson.ParseAsJson().ToString(), newJson.ParseAsJson().ToString()); // 生成デシリアライザでロードする var ff = new JsonFormatter(); var des = GltfDeserializer.Deserialize(parsed); ff.Clear(); GltfSerializer.Serialize(ff, des); var desJson = ff.ToString().ParseAsJson().ToString(" "); Assert.AreEqual(oldJson.ParseAsJson().ToString(), desJson.ParseAsJson().ToString()); } }
static void ImportMenu() { var path = EditorUtility.OpenFilePanel("open vrm", "", "vrm"); if (string.IsNullOrEmpty(path)) { return; } if (Application.isPlaying) { // load into scene var parser = new GltfParser(); parser.ParsePath(path); using (var context = new VRMImporterContext(parser)) { context.Load(); context.EnableUpdateWhenOffscreen(); context.ShowMeshes(); context.DisposeOnGameObjectDestroyed(); Selection.activeGameObject = context.Root; } } else { if (path.StartsWithUnityAssetPath()) { Debug.LogWarningFormat("disallow import from folder under the Assets"); return; } var assetPath = EditorUtility.SaveFilePanel("save prefab", "Assets", Path.GetFileNameWithoutExtension(path), "prefab"); if (string.IsNullOrEmpty(path)) { return; } if (!assetPath.StartsWithUnityAssetPath()) { Debug.LogWarningFormat("out of asset path: {0}", assetPath); return; } // import as asset var prefabPath = UnityPath.FromUnityPath(assetPath); var parser = new GltfParser(); parser.ParseGlb(File.ReadAllBytes(path)); Action <IEnumerable <string> > onCompleted = texturePaths => { // // after textures imported // var map = texturePaths.Select(x => { var texture = AssetDatabase.LoadAssetAtPath(x, typeof(Texture2D)); return(texture.name, texture); }).ToArray();
static void ImportMenu() { var path = EditorUtility.OpenFilePanel("open vrm", "", "vrm"); if (string.IsNullOrEmpty(path)) { return; } if (Application.isPlaying) { // load into scene var parser = new GltfParser(); parser.ParsePath(path); var context = new VRMImporterContext(parser); context.Load(); context.ShowMeshes(); context.EnableUpdateWhenOffscreen(); Selection.activeGameObject = context.Root; } else { if (path.StartsWithUnityAssetPath()) { Debug.LogWarningFormat("disallow import from folder under the Assets"); return; } var assetPath = EditorUtility.SaveFilePanel("save prefab", "Assets", Path.GetFileNameWithoutExtension(path), "prefab"); if (string.IsNullOrEmpty(path)) { return; } if (!assetPath.StartsWithUnityAssetPath()) { Debug.LogWarningFormat("out of asset path: {0}", assetPath); return; } // import as asset var prefabPath = UnityPath.FromUnityPath(assetPath); var parser = new GltfParser(); parser.ParseGlb(File.ReadAllBytes(path)); var context = new VRMImporterContext(parser); var editor = new VRMEditorImporterContext(context); editor.ExtractImages(prefabPath); EditorApplication.delayCall += () => { // // after textures imported // context.Load(); editor.SaveAsAsset(prefabPath); editor.Dispose(); }; } }
public static async Task <Material> CreateAsync(IAwaitCaller awaitCaller, GltfParser parser, int m_index, glTF_VRM_Material vrmMaterial, GetTextureAsyncFunc getTexture) { var item = vrmMaterial; var shaderName = item.shader; var shader = Shader.Find(shaderName); if (shader == null) { // // no shader // if (VRM_SHADER_NAMES.Contains(shaderName)) { Debug.LogErrorFormat("shader {0} not found. set Assets/VRM/Shaders/VRMShaders to Edit - project setting - Graphics - preloaded shaders", shaderName); } else { // #if VRM_DEVELOP // Debug.LogWarningFormat("unknown shader {0}.", shaderName); // #endif } return(await MaterialFactory.DefaultCreateMaterialAsync(awaitCaller, parser, m_index, getTexture)); } // // restore VRM material // var material = new Material(shader); // use material.name, because material name may renamed in GltfParser. material.name = parser.GLTF.materials[m_index].name; material.renderQueue = item.renderQueue; foreach (var kv in item.floatProperties) { material.SetFloat(kv.Key, kv.Value); } var offsetScaleMap = new Dictionary <string, float[]>(); foreach (var kv in item.vectorProperties) { if (item.textureProperties.ContainsKey(kv.Key)) { // texture offset & scale offsetScaleMap.Add(kv.Key, kv.Value); } else { // vector4 var v = new Vector4(kv.Value[0], kv.Value[1], kv.Value[2], kv.Value[3]); material.SetVector(kv.Key, v); } } foreach (var kv in item.textureProperties) { var(offset, scale) = (Vector2.zero, Vector2.one); if (offsetScaleMap.TryGetValue(kv.Key, out float[] value))
public static Model CreateVrmModel(GltfParser parser) { var storage = new Vrm10Storage(parser); var model = ModelLoader.Load(storage, Path.GetFileName(parser.TargetPath)); model.ConvertCoordinate(Coordinates.Unity); return(model); }
public Task <Material> CreateMaterialAsync(IAwaitCaller awaitCaller, GltfParser parser, int i, GetTextureAsyncFunc getTexture) { if (i == 0 && m_materials.Count == 0) { // dummy return(MaterialFactory.DefaultCreateMaterialAsync(awaitCaller, parser, i, getTexture)); } return(MToonMaterialItem.CreateAsync(awaitCaller, parser, i, m_materials[i], getTexture)); }
/// <summary> /// VRM1 で パースし、失敗したら Migration してから VRM1 でパースする /// </summary> /// <param name="path"></param> /// <param name="migrateToVrm1"></param> /// <returns></returns> public static string TryParseOrMigrate(string path, bool migrateToVrm1, out GltfParser parser) { // // Parse(parse glb, parser gltf json) // parser = new GltfParser(); parser.ParsePath(path); if (UniGLTF.Extensions.VRMC_vrm.GltfDeserializer.TryGet(parser.GLTF.extensions, out UniGLTF.Extensions.VRMC_vrm.VRMC_vrm vrm)) { // success return(default);
VrmLib.Model ReadModel(string path) { var bytes = MigrationVrm.Migrate(File.ReadAllBytes(path)); var parser = new GltfParser(); parser.Parse("migrated", bytes); var model = UniVRM10.VrmLoader.CreateVrmModel(parser); return(model); }
public IEnumerable <TextureImportParam> Enumerate(GltfParser parser) { for (int i = 0; i < parser.GLTF.materials.Count; ++i) { var vrmMaterial = m_vrm.materialProperties[i]; if (vrmMaterial.shader == MToon.Utils.ShaderName) { // MToon foreach (var kv in vrmMaterial.textureProperties) { // SRGB color or normalmap yield return(TextureFactory.Create(parser, kv.Value, kv.Key, default, default));
static GameObject Load(byte[] bytes, string path) { var parser = new GltfParser(); parser.Parse(path, bytes); using (var loader = new VRMImporterContext(parser)) { loader.Load(); loader.ShowMeshes(); return(loader.DisposeOnGameObjectDestroyed().gameObject); } }
static GameObject Import(byte[] bytes, FileInfo path) { var parser = new GltfParser(); parser.Parse(path.FullName, bytes); using (var loader = new RuntimeUnityBuilder(parser)) { loader.Load(); loader.ShowMeshes(); return(loader.DisposeOnGameObjectDestroyed().gameObject); } }
GameObject BuildGameObject(GltfParser parser, bool showMesh) { using (var loader = new RuntimeUnityBuilder(parser)) { loader.Load(); if (showMesh) { loader.ShowMeshes(); } loader.EnableUpdateWhenOffscreen(); return(loader.DisposeOnGameObjectDestroyed().gameObject); } }
public VRMImporterContext(GltfParser parser) : base(parser) { // parse VRM part if (glTF_VRM_extensions.TryDeserilize(GLTF.extensions, out glTF_VRM_extensions vrm)) { VRM = vrm; // override material importer MaterialFactory.CreateMaterialAsync = new VRMMaterialImporter(VRM.materialProperties).CreateMaterial; } else { throw new KeyNotFoundException("not vrm0"); } }
public static MaterialImportParam GetMaterialParam(GltfParser parser, int i) { // mtoon if (!TryCreateParam(parser, i, out MaterialImportParam param)) { // unlit if (!GltfUnlitMaterial.TryCreateParam(parser, i, out param)) { // pbr GltfPBRMaterial.TryCreateParam(parser, i, out param); } } return(param); }
public void MaterialImporterTest() { var parser = new GltfParser(); parser.ParsePath(AliciaPath); var vrmImporter = new VRMImporterContext(parser, null); var materialParam = new VRMMaterialImporter(vrmImporter.VRM).GetMaterialParam(parser, 0); Assert.AreEqual("VRM/MToon", materialParam.ShaderName); Assert.AreEqual("Alicia_body", materialParam.TextureSlots["_MainTex"].UnityObjectName); var(key, value) = materialParam.EnumerateSubAssetKeyValue().First(); Assert.AreEqual(new SubAssetKey(typeof(Texture2D), "Alicia_body"), key); }
/// <summary> /// SubAssetを外部ファイルに展開する /// </summary> public static void Extract(ScriptedImporter importer, GltfParser parser) { if (string.IsNullOrEmpty(importer.assetPath)) { return; } var path = $"{Path.GetDirectoryName(importer.assetPath)}/{Path.GetFileNameWithoutExtension(importer.assetPath)}.Extracted"; if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } // meta { foreach (var asset in importer.GetSubAssets <VRM10MetaObject>(importer.assetPath)) { asset.ExtractSubAsset($"{path}/{asset.name}.asset", false); } } { // expressions foreach (var asset in importer.GetSubAssets <VRM10Expression>(importer.assetPath)) { asset.ExtractSubAsset($"{path}/{asset.name}.asset", false); } // expressions foreach (var asset in importer.GetSubAssets <VRM10ExpressionAvatar>(importer.assetPath)) { asset.ExtractSubAsset($"{path}/{asset.name}.asset", false); } // external な expressionAvatar.Clips に 再代入する var expressionAvatar = importer.GetExternalObjectMap().Select(x => x.Value as VRM10ExpressionAvatar).FirstOrDefault(x => x != null); var expressions = importer.GetExternalObjectMap().Select(x => x.Value as VRM10Expression).Where(x => x != null).ToList(); expressionAvatar.Clips = expressions; var avatarPath = AssetDatabase.GetAssetPath(expressionAvatar); if (!string.IsNullOrEmpty(avatarPath)) { EditorUtility.SetDirty(expressionAvatar); AssetDatabase.WriteImportSettingsIfDirty(avatarPath); } } AssetDatabase.ImportAsset(importer.assetPath, ImportAssetOptions.ForceUpdate); }
/// <summary> /// Byte配列からVRMImporterContextの初期化をします /// </summary> /// <param name="vrmByteArray"></param> public void InitializeVrmContextFromByteArray(byte[] vrmByteArray) { #if UNIVRM_LEGACY_IMPORTER // VRMImporterContextがVRMを読み込む機能を提供します currentContext = new VRMImporterContext(); // GLB形式でJSONを取得しParseします currentContext.ParseGlb(vrmByteArray); #elif UNIVRM_0_68_IMPORTER var parser = new GltfParser(); parser.ParseGlb(vrmByteArray); currentContext = new VRMImporterContext(parser); #else #endif }
public static (SubAssetKey, TextureImportParam) Create(GltfParser parser, int index, Vector2 offset, Vector2 scale, string prop, float metallicFactor, float roughnessFactor) { switch (prop) { case TextureImportParam.NORMAL_PROP: return(GltfTextureImporter.CreateNormal(parser, index, offset, scale)); default: return(GltfTextureImporter.CreateSRGB(parser, index, offset, scale)); case TextureImportParam.OCCLUSION_PROP: case TextureImportParam.METALLIC_GLOSS_PROP: throw new NotImplementedException(); } }
public void MaterialImporterTest() { var migratedBytes = MigrationVrm.Migrate(File.ReadAllBytes(AliciaPath)); var parser = new GltfParser(); parser.Parse(AliciaPath, migratedBytes); var materialParam = Vrm10MaterialImporter.GetMaterialParam(parser, 0); Assert.AreEqual("VRM/MToon", materialParam.ShaderName); Assert.AreEqual("Alicia_body", materialParam.TextureSlots["_MainTex"].UnityObjectName); var(key, value) = materialParam.EnumerateSubAssetKeyValue().First(); Assert.AreEqual(new SubAssetKey(typeof(Texture2D), "Alicia_body"), key); }
/// <summary> /// 非同期でByte配列からVRMImporterContextの初期化をします /// </summary> /// <param name="vrmByteArray"></param> public async Task InitializeVrmContextFromByteArrayAsync(byte[] vrmByteArray) { #if UNIVRM_LEGACY_IMPORTER // VRMImporterContextがVRMを読み込む機能を提供します currentContext = new VRMImporterContext(); // GLB形式でJSONを取得しParseします await Task.Run(() => currentContext.ParseGlb(vrmByteArray)); #elif UNIVRM_0_68_IMPORTER var parser = new GltfParser(); await Task.Run(() => parser.ParseGlb(vrmByteArray)); currentContext = new VRMImporterContext(parser); #else #endif }
static void ImportRuntime(string path) { // load into scene var parser = new GltfParser(); parser.ParsePath(path); using (var context = new VRMImporterContext(parser)) { context.Load(); context.EnableUpdateWhenOffscreen(); context.ShowMeshes(); context.DisposeOnGameObjectDestroyed(); Selection.activeGameObject = context.Root; } }