/// <summary> /// /// * Texture(.png etc...)をディスクに書き出す /// * EditorApplication.delayCall で処理を進めて 書き出した画像が Asset として成立するのを待つ /// * 書き出した Asset から TextureImporter を取得して設定する /// /// </summary> /// <param name="importer"></param> /// <param name="dirName"></param> /// <param name="onCompleted"></param> public static void ExtractTextures(GltfParser parser, UnityPath textureDirectory, TextureEnumerator textureEnumerator, Texture2D[] subAssets, Action <Texture2D> addRemap, Action <IEnumerable <UnityPath> > onCompleted = null) { var extractor = new TextureExtractor(parser, textureDirectory, subAssets); foreach (var x in textureEnumerator(parser)) { extractor.Extract(x); } EditorApplication.delayCall += () => { // Wait for the texture assets to be imported foreach (var kv in extractor.Textures) { var targetPath = kv.Key; var param = kv.Value; // remap var externalObject = targetPath.LoadAsset <Texture2D>(); if (externalObject != null) { addRemap(externalObject); } } if (onCompleted != null) { onCompleted(extractor.Textures.Keys); } }; }
static void ExtractMaterialsAndTextures(ScriptedImporter self, GltfParser parser) { if (string.IsNullOrEmpty(self.assetPath)) { return; } Action <Texture2D> addRemap = externalObject => { self.AddRemap(new AssetImporter.SourceAssetIdentifier(typeof(UnityEngine.Texture2D), externalObject.name), externalObject); }; Action <IEnumerable <UnityPath> > onCompleted = _ => { AssetDatabase.ImportAsset(self.assetPath, ImportAssetOptions.ForceUpdate); self.ExtractMaterials(); AssetDatabase.ImportAsset(self.assetPath, ImportAssetOptions.ForceUpdate); }; var assetPath = UnityPath.FromFullpath(parser.TargetPath); var dirName = $"{assetPath.FileNameWithoutExtension}.Textures"; TextureExtractor.ExtractTextures(parser, assetPath.Parent.Child(dirName), GltfTextureEnumerator.Enumerate, self.GetSubAssets <UnityEngine.Texture2D>(self.assetPath).ToArray(), addRemap, onCompleted ); }
public static TextureImportParam CreateSRGB(GltfParser parser, int textureIndex, Vector2 offset, Vector2 scale) { var name = CreateNameExt(parser.GLTF, textureIndex, TextureImportTypes.sRGB); var sampler = CreateSampler(parser.GLTF, textureIndex); GetTextureBytesAsync getTextureBytesAsync = () => Task.FromResult(ToArray(parser.GLTF.GetImageBytesFromTextureIndex(parser.Storage, textureIndex))); return(new TextureImportParam(name, offset, scale, sampler, TextureImportTypes.sRGB, default, default, getTextureBytesAsync, default, default, default, default, default));
public void TextureExtractTest() { var path = GetGltfTestModelPath("BoomBox.glb"); if (path == null) { return; } // parse var parser = new GltfParser(); parser.ParsePath(path.FullName); // load var loader = new ImporterContext(parser); loader.Load(); // extractor var extractor = new TextureExtractor(parser, UnityPath.FromUnityPath(""), loader.TextureFactory.Textures.Select(x => (new SubAssetKey(typeof(Texture2D), x.Texture.name), x.Texture)).ToArray()); var m = GltfTextureEnumerator.EnumerateTexturesReferencedByMaterials(parser, 0).FirstOrDefault(x => x.Item1.Name == "texture_1.standard"); Assert.Catch <NotImplementedException>(() => extractor.Extract(m.Item1, m.Item2)); }
public void GltfSampleModelsTest_DamagedHelmet() { var env = System.Environment.GetEnvironmentVariable("GLTF_SAMPLE_MODELS"); if (string.IsNullOrEmpty(env)) { return; } var root = new DirectoryInfo($"{env}/2.0"); if (!root.Exists) { return; } { var path = Path.Combine(root.FullName, "DamagedHelmet/glTF-Binary/DamagedHelmet.glb"); var parser = new GltfParser(); parser.ParsePath(path); var materialParam = new GltfMaterialImporter().GetMaterialParam(parser, 0); Assert.AreEqual("Standard", materialParam.ShaderName); Assert.AreEqual(5, materialParam.TextureSlots.Count); var(key, value) = materialParam.EnumerateSubAssetKeyValue().First(); Assert.AreEqual(new SubAssetKey(typeof(Texture2D), "texture_0"), key); } }
static void OnGUIMaterial(GltfScriptedImporter importer, GltfParser parser) { var canExtract = !importer.GetExternalObjectMap().Any(x => x.Value is Material || x.Value is Texture2D); using (new TmpGuiEnable(canExtract)) { if (GUILayout.Button("Extract Materials And Textures ...")) { importer.ExtractMaterialsAndTextures(); } } // ObjectMap s_foldMaterials = EditorGUILayout.Foldout(s_foldMaterials, "Remapped Materials"); if (s_foldMaterials) { DrawRemapGUI <UnityEngine.Material>(importer, parser.GLTF.materials.Select(x => x.name)); } s_foldTextures = EditorGUILayout.Foldout(s_foldTextures, "Remapped Textures"); if (s_foldTextures) { DrawRemapGUI <UnityEngine.Texture2D>(importer, parser.EnumerateTextures().Select(x => x.Name)); } if (GUILayout.Button("Clear")) { importer.ClearExternalObjects <UnityEngine.Material>(); importer.ClearExternalObjects <UnityEngine.Texture2D>(); } }
public void UniGLTFSimpleSceneTest() { var go = CreateSimpleScene(); // export var gltf = new glTF(); string json = null; using (var exporter = new gltfExporter(gltf)) { exporter.Prepare(go); exporter.Export(MeshExportSettings.Default, AssetTextureUtil.IsTextureEditorAsset, AssetTextureUtil.GetTextureBytesWithMime); // remove empty buffer gltf.buffers.Clear(); json = gltf.ToJson(); } // parse var parser = new GltfParser(); parser.ParseJson(json, new SimpleStorage(new ArraySegment <byte>())); // import using (var context = new ImporterContext(parser)) { context.Load(); AssertAreEqual(go.transform, context.Root.transform); } }
static void ExtractMaterialsAndTextures(ScriptedImporter self, GltfParser parser, EnumerateAllTexturesDistinctFunc enumTextures, Func <string, string> textureDir, Func <string, string> materialDir) { if (string.IsNullOrEmpty(self.assetPath)) { return; } Action <SubAssetKey, Texture2D> addRemap = (key, externalObject) => { self.AddRemap(new AssetImporter.SourceAssetIdentifier(key.Type, key.Name), externalObject); }; Action <IEnumerable <UnityPath> > onCompleted = _ => { AssetDatabase.ImportAsset(self.assetPath, ImportAssetOptions.ForceUpdate); self.ExtractMaterials(materialDir); AssetDatabase.ImportAsset(self.assetPath, ImportAssetOptions.ForceUpdate); }; var assetPath = UnityPath.FromFullpath(parser.TargetPath); var dirName = textureDir(assetPath.Value); // $"{assetPath.FileNameWithoutExtension}.Textures"; TextureExtractor.ExtractTextures(parser, assetPath.Parent.Child(dirName), enumTextures, self.GetSubAssets <UnityEngine.Texture2D>(self.assetPath).ToArray(), addRemap, onCompleted ); }
static void OnGUIAnimation(GltfScriptedImporter importer, GltfParser parser) { foreach (var a in parser.GLTF.animations) { GUILayout.Label(a.name); } }
static void RuntimeLoad(FileInfo gltf, int subStrStart) { var parser = new GltfParser(); try { parser.ParsePath(gltf.FullName); } catch (Exception ex) { Debug.LogError($"ParseError: {gltf}"); Debug.LogException(ex); } try { using (var importer = new ImporterContext(parser)) { importer.Load(); } } catch (Exception ex) { Message(gltf.FullName.Substring(subStrStart), ex); } }
public TextureExtractor(GltfParser parser, UnityPath textureDirectory, UnityEngine.Texture2D[] subAssets) { m_parser = parser; m_textureDirectory = textureDirectory; m_textureDirectory.EnsureFolder(); m_subAssets = subAssets; }
public override void OnEnable() { base.OnEnable(); m_importer = target as GltfScriptedImporter; m_parser = new GltfParser(); m_parser.ParsePath(m_importer.assetPath); }
public static void OnGUIAnimation(GltfParser parser) { for (int i = 0; i < parser.GLTF.animations.Count; ++i) { var a = parser.GLTF.animations[i]; GUILayout.Label($"{i}: {a.name}"); } }
public TextureExtractor(ScriptedImporter importer) { // parse GLTF m_parser = new GltfParser(); m_parser.ParsePath(importer.assetPath); m_path = $"{Path.GetDirectoryName(importer.assetPath)}/{Path.GetFileNameWithoutExtension(importer.assetPath)}.Textures"; m_subAssets = importer.GetSubAssets <UnityEngine.Texture2D>(importer.assetPath).ToArray(); }
private (GameObject, IReadOnlyList <VRMShaders.MaterialFactory.MaterialLoadInfo>) ToUnity(byte[] bytes) { // Vrm => Model var parser = new UniGLTF.GltfParser(); parser.Parse("tmp.vrm", bytes); return(ToUnity(parser)); }
public static (SubAssetKey, TextureImportParam Param) CreateSRGB(GltfParser parser, int textureIndex, Vector2 offset, Vector2 scale) { var gltfTexture = parser.GLTF.textures[textureIndex]; var gltfImage = parser.GLTF.images[gltfTexture.source]; var name = TextureImportName.GetUnityObjectName(TextureImportTypes.sRGB, gltfTexture.name, gltfImage.uri); var sampler = CreateSampler(parser.GLTF, textureIndex); GetTextureBytesAsync getTextureBytesAsync = () => Task.FromResult(ToArray(parser.GLTF.GetImageBytesFromTextureIndex(parser.Storage, textureIndex))); var key = new SubAssetKey(typeof(Texture2D), name); var param = new TextureImportParam(name, gltfImage.GetExt(), gltfImage.uri, offset, scale, sampler, TextureImportTypes.sRGB, default, default, getTextureBytesAsync, default, default, default, default, default);
public void VersionChecker() { Assert.False(GltfParser.IsGeneratedUniGLTFAndOlderThan("hoge", 1, 16)); Assert.False(GltfParser.IsGeneratedUniGLTFAndOlderThan("UniGLTF-1.16", 1, 16)); Assert.True(GltfParser.IsGeneratedUniGLTFAndOlderThan("UniGLTF-1.15", 1, 16)); Assert.False(GltfParser.IsGeneratedUniGLTFAndOlderThan("UniGLTF-11.16", 1, 16)); Assert.True(GltfParser.IsGeneratedUniGLTFAndOlderThan("UniGLTF-0.16", 1, 16)); Assert.True(GltfParser.IsGeneratedUniGLTFAndOlderThan("UniGLTF", 1, 16)); }
public static void OnGUIMaterial(ScriptedImporter importer, GltfParser parser) { var canExtract = !importer.GetExternalObjectMap().Any(x => x.Value is Material || x.Value is Texture2D); using (new TmpGuiEnable(canExtract)) { if (GUILayout.Button("Extract Materials And Textures ...")) { ExtractMaterialsAndTextures(importer, parser); } } // // Draw ExternalObjectMap // s_foldMaterials = EditorGUILayout.Foldout(s_foldMaterials, "Remapped Materials"); if (s_foldMaterials) { DrawRemapGUI <UnityEngine.Material>(importer, parser.GLTF.materials.Select(x => x.name)); } s_foldTextures = EditorGUILayout.Foldout(s_foldTextures, "Remapped Textures"); if (s_foldTextures) { var names = GltfTextureEnumerator.Enumerate(parser) .Select(x => { if (x.TextureType != TextureImportTypes.StandardMap && !string.IsNullOrEmpty(x.Uri)) { // GLTF の 無変換テクスチャーをスキップする return(null); } switch (x.TextureType) { case TextureImportTypes.NormalMap: return(x.GltfName); default: return(x.ConvertedName); } }) .Where(x => !string.IsNullOrEmpty(x)) ; DrawRemapGUI <UnityEngine.Texture2D>(importer, names); } if (GUILayout.Button("Clear")) { importer.ClearExternalObjects <UnityEngine.Material>(); importer.ClearExternalObjects <UnityEngine.Texture2D>(); } }
public void MeshHasNoRendererTest() { var go = new GameObject("mesh_has_no_renderer"); try { { var cube = GameObject.CreatePrimitive(PrimitiveType.Cube); cube.transform.SetParent(go.transform); UnityEngine.Object.DestroyImmediate(cube.GetComponent <MeshRenderer>()); } // export var gltf = new glTF(); string json; using (var exporter = new gltfExporter(gltf)) { exporter.Prepare(go); exporter.Export(UniGLTF.MeshExportSettings.Default, AssetTextureUtil.IsTextureEditorAsset, AssetTextureUtil.GetTextureBytesWithMime); json = gltf.ToJson(); } Assert.AreEqual(0, gltf.meshes.Count); Assert.AreEqual(1, gltf.nodes.Count); Assert.AreEqual(-1, gltf.nodes[0].mesh); // import { var parser = new GltfParser(); parser.ParseJson(json, new SimpleStorage(new ArraySegment <byte>(new byte[1024 * 1024]))); using (var context = new ImporterContext(parser)) { context.Load(); Assert.AreEqual(1, context.Root.transform.GetChildren().Count()); { var child = context.Root.transform.GetChild(0); Assert.IsNull(child.GetSharedMesh()); } } } } finally { GameObject.DestroyImmediate(go); } }
public static IEnumerable <TextureImportParam> Enumerate(GltfParser parser) { var used = new HashSet <TextureImportParam>(); foreach (var material in parser.GLTF.materials) { foreach (var textureInfo in EnumerateTextures(parser, material)) { if (used.Add(textureInfo)) { yield return(textureInfo); } } } }
public TextureExtractor(string assetPath, UnityEngine.Texture2D[] subAssets) { // parse GLTF m_parser = new GltfParser(); m_parser.ParsePath(assetPath); m_path = $"{Path.GetDirectoryName(assetPath)}/{Path.GetFileNameWithoutExtension(assetPath)}.Textures"; SafeCreateDirectory(m_path); if (assetPath == null) { throw new ArgumentNullException(); } m_subAssets = subAssets; }
/// <summary> /// glTF 全体で使うテクスチャーをユニークになるように列挙する /// </summary> /// <param name="parser"></param> /// <returns></returns> public static IEnumerable <TextureImportParam> EnumerateAllTexturesDistinct(GltfParser parser) { var used = new HashSet <string>(); for (int i = 0; i < parser.GLTF.materials.Count; ++i) { foreach (var textureInfo in EnumerateTexturesForMaterial(parser, i)) { if (used.Add(textureInfo.ExtractKey)) { yield return(textureInfo); } } } }
/// <summary> /// glb をパースして、UnityObject化、さらにAsset化する /// </summary> /// <param name="scriptedImporter"></param> /// <param name="context"></param> /// <param name="reverseAxis"></param> public static void Import(ScriptedImporter scriptedImporter, AssetImportContext context, Axises reverseAxis) { #if VRM_DEVELOP Debug.Log("OnImportAsset to " + scriptedImporter.assetPath); #endif // // Parse(parse glb, parser gltf json) // var parser = new GltfParser(); parser.ParsePath(scriptedImporter.assetPath); // // Import(create unity objects) // var externalObjectMap = scriptedImporter.GetExternalObjectMap(); using (var loaded = new ImporterContext(parser, null, externalObjectMap.Where(x => x.Value != null).Select(x => (x.Value.name, x.Value)).Concat( EnumerateTexturesFromUri(externalObjectMap, parser, UnityPath.FromUnityPath(scriptedImporter.assetPath).Parent)))) { // settings TextureImporters foreach (var textureInfo in GltfTextureEnumerator.Enumerate(parser.GLTF)) { TextureImporterConfigurator.Configure(textureInfo, loaded.TextureFactory.ExternalMap); } loaded.InvertAxis = reverseAxis; loaded.Load(); loaded.ShowMeshes(); loaded.TransferOwnership(o => { #if VRM_DEVELOP Debug.Log($"[{o.GetType().Name}] {o.name} will not destroy"); #endif context.AddObjectToAsset(o.name, o); if (o is GameObject) { // Root GameObject is main object context.SetMainObject(loaded.Root); } return(true); }); } }
public static IEnumerable <TextureImportParam> EnumerateTexturesForMaterial(GltfParser parser, int i) { var m = parser.GLTF.materials[i]; int?metallicRoughnessTexture = default; if (m.pbrMetallicRoughness != null) { // base color if (m.pbrMetallicRoughness?.baseColorTexture != null) { yield return(GltfPBRMaterial.BaseColorTexture(parser, m)); } // metallic roughness if (m.pbrMetallicRoughness?.metallicRoughnessTexture != null && m.pbrMetallicRoughness.metallicRoughnessTexture.index != -1) { metallicRoughnessTexture = m.pbrMetallicRoughness?.metallicRoughnessTexture?.index; } } // emission if (m.emissiveTexture != null) { var(offset, scale) = GltfMaterialImporter.GetTextureOffsetAndScale(m.emissiveTexture); yield return(GltfTextureImporter.CreateSRGB(parser, m.emissiveTexture.index, offset, scale)); } // normal if (m.normalTexture != null) { yield return(GltfPBRMaterial.NormalTexture(parser, m)); } // occlusion int?occlusionTexture = default; if (m.occlusionTexture != null && m.occlusionTexture.index != -1) { occlusionTexture = m.occlusionTexture.index; } // metallicSmooth and occlusion if (metallicRoughnessTexture.HasValue || occlusionTexture.HasValue) { yield return(GltfPBRMaterial.StandardTexture(parser, m)); } }
public MaterialImportParam GetMaterialParam(GltfParser parser, int i) { foreach (var tryCreate in GltfMaterialParamProcessors) { if (tryCreate(parser, i, out MaterialImportParam param)) { return(param); } } // fallback #if VRM_DEVELOP Debug.LogWarning($"material: {i} out of range. fallback"); #endif return(new MaterialImportParam(MaterialName(i, null), GltfPBRMaterial.ShaderName)); }
public static TextureImportParam StandardTexture(GltfParser parser, glTFMaterial src) { var metallicFactor = 1.0f; var roughnessFactor = 1.0f; if (src.pbrMetallicRoughness != null) { metallicFactor = src.pbrMetallicRoughness.metallicFactor; roughnessFactor = src.pbrMetallicRoughness.roughnessFactor; } return(TextureFactory.CreateStandard(parser, src.pbrMetallicRoughness?.metallicRoughnessTexture?.index, src.occlusionTexture?.index, metallicFactor, roughnessFactor)); }
/// <summary> /// for export /// </summary> public Vrm10Storage() { m_parser = new UniGLTF.GltfParser { GLTF = new UniGLTF.glTF() { extensionsUsed = new List <string>(), } }; Buffers = new List <UniGLTF.IBytesBuffer>() { new UniGLTF.ArrayByteBuffer() }; Gltf.AddBuffer(Buffers[0]); }
public static IEnumerable <TextureImportParam> EnumerateTextures(GltfParser parser, glTFMaterial m) { int?metallicRoughnessTexture = default; if (m.pbrMetallicRoughness != null) { // base color if (m.pbrMetallicRoughness?.baseColorTexture != null) { yield return(PBRMaterialItem.BaseColorTexture(parser, m)); } // metallic roughness if (m.pbrMetallicRoughness?.metallicRoughnessTexture != null && m.pbrMetallicRoughness.metallicRoughnessTexture.index != -1) { metallicRoughnessTexture = m.pbrMetallicRoughness?.metallicRoughnessTexture?.index; } } // emission if (m.emissiveTexture != null) { var(offset, scale) = MaterialFactory.GetTextureOffsetAndScale(m.emissiveTexture); yield return(TextureFactory.CreateSRGB(parser, m.emissiveTexture.index, offset, scale)); } // normal if (m.normalTexture != null) { yield return(PBRMaterialItem.NormalTexture(parser, m)); } // occlusion int?occlusionTexture = default; if (m.occlusionTexture != null && m.occlusionTexture.index != -1) { occlusionTexture = m.occlusionTexture.index; } // metallicSmooth and occlusion if (metallicRoughnessTexture.HasValue || occlusionTexture.HasValue) { yield return(PBRMaterialItem.StandardTexture(parser, m)); } }
public static void OnGUI(ScriptedImporter importer, GltfParser parser, EnumerateAllTexturesDistinctFunc enumTextures) { var hasExternal = importer.GetExternalObjectMap().Any(x => x.Value is Material || x.Value is Texture2D); using (new TmpGuiEnable(!hasExternal)) { if (GUILayout.Button("Extract Materials And Textures ...")) { ExtractMaterialsAndTextures(importer, parser, enumTextures); } } // // Draw ExternalObjectMap // s_foldMaterials = EditorGUILayout.Foldout(s_foldMaterials, "Remapped Materials"); if (s_foldMaterials) { importer.DrawRemapGUI <UnityEngine.Material>(parser.GLTF.materials.Select(x => new SubAssetKey(typeof(Material), x.name))); } s_foldTextures = EditorGUILayout.Foldout(s_foldTextures, "Remapped Textures"); if (s_foldTextures) { importer.DrawRemapGUI <UnityEngine.Texture2D>(enumTextures(parser) .Where(x => { var(key, param) = x; if ((param.TextureType == TextureImportTypes.sRGB || param.TextureType == TextureImportTypes.NormalMap) && !string.IsNullOrEmpty(param.Uri)) { // GLTF の 無変換テクスチャーをスキップする return(false); } return(true); }) .Select(x => x.Key) ); } if (GUILayout.Button("Clear")) { importer.ClearExternalObjects <UnityEngine.Material>(); importer.ClearExternalObjects <UnityEngine.Texture2D>(); } }
public static TextureImportParam StandardTexture(GltfParser parser, glTFMaterial src) { var metallicFactor = 1.0f; var roughnessFactor = 1.0f; if (src.pbrMetallicRoughness != null) { metallicFactor = src.pbrMetallicRoughness.metallicFactor; roughnessFactor = src.pbrMetallicRoughness.roughnessFactor; } var(offset, scale) = GltfMaterialImporter.GetTextureOffsetAndScale(src.pbrMetallicRoughness.metallicRoughnessTexture); return(GltfTextureImporter.CreateStandard(parser, src.pbrMetallicRoughness?.metallicRoughnessTexture?.index, src.occlusionTexture?.index, offset, scale, metallicFactor, roughnessFactor)); }