/// <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 }
VrmLib.Model ReadModel(string path) { var bytes = MigrationVrm.Migrate(File.ReadAllBytes(path)); var data = new GlbLowLevelParser(path, bytes).Parse(); var model = ModelReader.Read(data); return(model); }
static GameObject Load(byte[] bytes, string path) { var data = new GlbLowLevelParser(path, bytes).Parse(); using (var loader = new VRMImporterContext(data)) { var loaded = loader.Load(); loaded.ShowMeshes(); return(loaded.gameObject); } }
public void MaterialImporterTest() { var migratedBytes = MigrationVrm.Migrate(File.ReadAllBytes(AliciaPath)); var data = new GlbLowLevelParser(AliciaPath, migratedBytes).Parse(); var matDesc = new Vrm10MaterialDescriptorGenerator().Get(data, 0); Assert.AreEqual("Alicia_body", matDesc.Name); Assert.AreEqual("Hidden/VRM10/vrmc_materials_mtoon", matDesc.ShaderName); Assert.AreEqual("Alicia_body", matDesc.TextureSlots["_MainTex"].UnityObjectName); Assert.AreEqual("Alicia_body", matDesc.TextureSlots["_ShadeTex"].UnityObjectName); AreColorEqualApproximately(new Color(1, 1, 1, 1), matDesc.Colors["_Color"]); ColorUtility.TryParseHtmlString("#FFDDD6", out var shadeColor); AreColorEqualApproximately(shadeColor, matDesc.Colors["_ShadeColor"]); Assert.AreEqual(1.0f - 0.1f, matDesc.FloatValues["_GiEqualization"]); var(key, value) = matDesc.EnumerateSubAssetKeyValue().First(); Assert.AreEqual(new SubAssetKey(typeof(Texture2D), "Alicia_body"), key); }
/// <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); #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 = await currentContext.LoadAsync(); return(currentInstance.Root); #else return(null); #endif }
/// <summary> /// VRM-1 の thumbnail テクスチャー。gltf.textures ではなく gltf.images の参照であることに注意(sampler等の設定が無い) /// </summary> public static bool TryGetMetaThumbnailTextureImportParam(GltfData data, UniGLTF.Extensions.VRMC_vrm.VRMC_vrm vrm, out (SubAssetKey, TextureDescriptor) value) { if (vrm?.Meta?.ThumbnailImage == null) { value = default; return(false); } var thumbnailImage = vrm.Meta.ThumbnailImage; if (!thumbnailImage.HasValue) { value = default; return(false); } var imageIndex = thumbnailImage.Value; if (imageIndex < 0 || imageIndex >= data.GLTF.images.Count) { value = default; return(false); } var gltfImage = data.GLTF.images[imageIndex]; // data.GLTF.textures は前処理によりユニーク性がある // unique な名前を振り出す var used = new HashSet <string>(data.GLTF.textures.Select(x => x.name)); var imageName = gltfImage.name; if (string.IsNullOrEmpty(imageName)) { imageName = THUMBNAIL_NAME; } var uniqueName = GlbLowLevelParser.FixNameUnique(used, imageName); value = GltfTextureImporter.CreateSrgbFromOnlyImage(data, imageIndex, uniqueName, gltfImage.uri); return(true); }
static GameObject Load(FileInfo gltf, DirectoryInfo root, byte[] bytes = null) { GltfData data = null; try { if (bytes != null) { data = new GlbLowLevelParser(gltf.FullName, bytes).Parse(); } else { data = new GlbFileParser(gltf.FullName).Parse(); } } catch (Exception ex) { Debug.LogError($"ParseError: {gltf}"); Debug.LogException(ex); return(null); } try { using (data) using (var importer = new VRMImporterContext(new VRMData(data))) { return(importer.Load().gameObject); } } catch (Exception ex) { Message(gltf.FullName.Substring(root.FullName.Length), ex); return(null); } }
/// <summary> /// vrm1 をパースする。vrm0 からのマイグレートもできる。 /// </summary> /// <param name="path"></param> /// <param name="bytes"></param> /// <param name="doMigrate"></param> /// <param name="vrm1Data">成功した場合非 null</param> /// <param name="migration">doMigrate==true の場合、関連情報が入る</param> /// <returns>GltfDataを作成できたときは Return するのでDisposeすること</returns> public static GltfData ParseOrMigrate(string path, byte[] bytes, bool doMigrate, out Vrm10Data vrm1Data, out MigrationData migration) { var data = new GlbLowLevelParser(path, bytes).Parse(); byte[] migrated = default; byte[] migratedBytes = null; Migration.Vrm0Meta oldMeta = default; try { if (UniGLTF.Extensions.VRMC_vrm.GltfDeserializer.TryGet(data.GLTF.extensions, out UniGLTF.Extensions.VRMC_vrm.VRMC_vrm vrm)) { // success vrm1Data = new Vrm10Data(data, vrm); migration = default; return(data); } if (!doMigrate) { vrm1Data = default; migration = new MigrationData("Not vrm1 and no migration"); return(data); } // try migrateion // Migration.Vrm0Meta oldMeta = default; JsonNode json = data.Json.ParseAsJson(); if (!json.TryGet("extensions", out JsonNode extensions)) { vrm1Data = default; migration = new MigrationData("gltf: no extensions"); return(data); } if (!extensions.TryGet("VRM", out JsonNode vrm0)) { vrm1Data = default; migration = new MigrationData("gltf: no vrm0"); return(data); } // found vrm0 oldMeta = Migration.Vrm0Meta.FromJsonBytes(json); if (oldMeta == null) { throw new NullReferenceException("oldMeta"); } // try migrate... migrated = MigrationVrm.Migrate(data); if (migrated == null) { vrm1Data = default; migration = new MigrationData("Found vrm0. But fail to migrate", oldMeta); return(data); } if (VRMShaders.Symbols.VRM_DEVELOP) { // load 時の右手左手座標変換でバッファが破壊的変更されるので、コピーを作っている migratedBytes = migrated.Select(x => x).ToArray(); } } catch (Exception ex) { // 何か起きた。Dispose は頼む vrm1Data = default; migration = new MigrationData(ex.Message); return(data); } // マイグレーション前を破棄 data.Dispose(); // マイグレーション結果をパースする var migratedData = new GlbLowLevelParser(data.TargetPath, migrated).Parse(); try { if (!UniGLTF.Extensions.VRMC_vrm.GltfDeserializer.TryGet(migratedData.GLTF.extensions, out VRMC_vrm vrm)) { // migration した結果のパースに失敗した ! vrm1Data = default; migration = new MigrationData("vrm0: migrate but error ?", oldMeta, migrated); return(migratedData); } { // success vrm1Data = new Vrm10Data(migratedData, vrm); migration = new MigrationData("vrm0: migrated", oldMeta, migratedBytes); return(migratedData); } } catch (Exception ex) { // 何か起きた。Dispose は頼む vrm1Data = default; migration = new MigrationData(ex.Message); return(migratedData); } }
private static async Task <Vrm10Instance> LoadAsync( string name, byte[] bytes, bool canLoadVrm0X, bool normalizeTransform, bool showMeshes, IAwaitCaller awaitCaller, IMaterialDescriptorGenerator materialGenerator, VrmMetaInformationCallback vrmMetaInformationCallback, CancellationToken ct) { ct.ThrowIfCancellationRequested(); if (awaitCaller == null) { throw new ArgumentNullException(); } using (var gltfData = new GlbLowLevelParser(name, bytes).Parse()) { // 1. Try loading as vrm-1.0 var instance = await TryLoadingAsVrm10Async( gltfData, normalizeTransform, showMeshes, awaitCaller, materialGenerator, vrmMetaInformationCallback, ct); if (instance != null) { if (ct.IsCancellationRequested) { UnityObjectDestoyer.DestroyRuntimeOrEditor(instance.gameObject); ct.ThrowIfCancellationRequested(); } return(instance); } // 2. Stop loading if not allowed migration. if (!canLoadVrm0X) { throw new Exception($"Failed to load as VRM 1.0: {name}"); } // 3. Try migration from vrm-0.x into vrm-1.0 var migratedInstance = await TryMigratingFromVrm0XAsync( gltfData, normalizeTransform, showMeshes, awaitCaller, materialGenerator, vrmMetaInformationCallback, ct); if (migratedInstance != null) { if (ct.IsCancellationRequested) { UnityObjectDestoyer.DestroyRuntimeOrEditor(migratedInstance.gameObject); ct.ThrowIfCancellationRequested(); } return(migratedInstance); } // 4. Failed loading. throw new Exception($"Failed to load: {name}"); } }
/// <summary> /// /// </summary> /// <param name="data"></param> /// <param name="vrm1Data"></param> /// <param name="migration"></param> /// <returns>Migrated GltfData if succeeded. Must Dispose</returns> public static GltfData Migrate(GltfData data, out Vrm10Data vrm1Data, out MigrationData migration) { var json = data.Json.ParseAsJson(); if (!json.TryGet("extensions", out JsonNode extensions)) { vrm1Data = default; migration = new MigrationData("gltf: no extensions"); return(null); } if (!extensions.TryGet("VRM", out JsonNode vrm0)) { vrm1Data = default; migration = new MigrationData("gltf: no vrm0"); return(null); } // found vrm0 var oldMeta = Migration.Vrm0Meta.FromJsonBytes(json); if (oldMeta == null) { throw new NullReferenceException("oldMeta"); } // try migrate... byte[] migrated = null; try { migrated = MigrationVrm.Migrate(data); if (migrated == null) { vrm1Data = default; migration = new MigrationData("Found vrm0. But fail to migrate", oldMeta); return(null); } } catch (MigrationException ex) { // migration 失敗 vrm1Data = default; migration = new MigrationData(ex.ToString(), oldMeta); return(null); } catch (Exception ex) { // その他のエラー vrm1Data = default; migration = new MigrationData(ex.ToString(), oldMeta); return(null); } byte[] debugCopy = null; if (VRMShaders.Symbols.VRM_DEVELOP) { // load 時の右手左手座標変換でバッファが破壊的変更されるので、コピーを作っている debugCopy = migrated.Select(x => x).ToArray(); } // マイグレーション結果をパースする var migratedData = new GlbLowLevelParser(data.TargetPath, migrated).Parse(); try { if (!UniGLTF.Extensions.VRMC_vrm.GltfDeserializer.TryGet(migratedData.GLTF.extensions, out VRMC_vrm vrm)) { // migration した結果のパースに失敗した ! vrm1Data = default; migration = new MigrationData("vrm0: migrate but error ?", oldMeta, migrated); // 破棄 migratedData.Dispose(); return(null); } { // success. 非null値が返るのはここだけ。 vrm1Data = new Vrm10Data(migratedData, vrm); migration = new MigrationData("vrm0: migrated", oldMeta, debugCopy); return(migratedData); } } catch (Exception ex) { Debug.LogWarning(ex); vrm1Data = default; migration = new MigrationData(ex.Message); // 破棄 migratedData.Dispose(); return(null); } }