public TextureExtractor(GltfData data, UnityPath textureDirectory, IReadOnlyDictionary <SubAssetKey, Texture> subAssets) { m_data = data; m_textureDirectory = textureDirectory; m_textureDirectory.EnsureFolder(); m_subAssets = subAssets; }
public override void OnDisable() { m_data.Dispose(); m_data = null; base.OnDisable(); }
/// <summary> /// glTF の Texture が存在せず Image のみのものを、Texture として扱いたい場合の関数. /// </summary> public static (SubAssetKey, TextureDescriptor) CreateSrgbFromOnlyImage(GltfData data, int imageIndex, string uniqueName, string uri) { var name = TextureImportName.GetUnityObjectName(TextureImportTypes.sRGB, uniqueName, uri); var texDesc = new TextureDescriptor( name, Vector2.zero, Vector2.one,
/// <summary> /// Extract をテスト /// </summary> /// <param name="gltf"></param> /// <param name="root"></param> static void EditorLoad(FileInfo gltf, int subStrStart) { GltfData data = null; try { data = new AutoGltfFileParser(gltf.FullName).Parse(); } catch (Exception ex) { Debug.LogError($"ParseError: {gltf}"); Debug.LogException(ex); } // should unique using (data) { var gltfTextures = new GltfTextureDescriptorGenerator(data).Get().GetEnumerable() .Select(x => x.SubAssetKey) .ToArray(); var distinct = gltfTextures.Distinct().ToArray(); Assert.True(gltfTextures.Length == distinct.Length); Assert.True(gltfTextures.SequenceEqual(distinct)); } }
public void OnGUI(ScriptedImporter importer, GltfData data) { if (!HasKeys) { EditorGUILayout.HelpBox("no animations", MessageType.Info); return; } if (CanExtract(importer)) { if (GUILayout.Button("Extract Animation ...")) { Extract(importer, data); } EditorGUILayout.HelpBox("Extract subasset to external object and overwrite remap", MessageType.Info); } else { if (GUILayout.Button("Clear extraction")) { ClearExternalObjects(importer, typeof(AnimationClip)); } EditorGUILayout.HelpBox("Clear remap. All remap use subAsset", MessageType.Info); } DrawRemapGUI <AnimationClip>(importer.GetExternalObjectMap()); }
public void UniGLTFSimpleSceneTest() { var go = CreateSimpleScene(); // export var data = new ExportingGltfData(); string json = null; using (var exporter = new gltfExporter(data, new GltfExportSettings())) { exporter.Prepare(go); exporter.Export(new EditorTextureSerializer()); // remove empty buffer data.GLTF.buffers.Clear(); json = data.GLTF.ToJson(); } // parse var parsed = GltfData.CreateFromExportForTest(data); // import using (var context = new ImporterContext(parsed)) using (var loaded = context.Load()) { AssertAreEqual(go.transform, loaded.transform); } }
/// <summary> /// glTF から 頂点バッファと index バッファ、BlendShape を蓄える。 /// 右手系と左手系の反転(ZもしくはX軸の反転)も実行する。 /// </summary> public void LoadFromGltf(GltfData data, int meshIndex, IAxisInverter inverter) { Profiler.BeginSample("MeshData.CreateFromGltf"); Clear(); var gltfMesh = data.GLTF.meshes[meshIndex]; var name = gltfMesh.name; if (string.IsNullOrEmpty(name)) { name = $"UniGLTF import#{meshIndex}"; } Name = name; if (HasSharedVertexBuffer(gltfMesh)) { ImportMeshSharingVertexBuffer(data, gltfMesh, inverter); } else { ImportMeshIndependentVertexBuffer(data, gltfMesh, inverter); } RenameBlendShape(gltfMesh); DropUnusedVertices(); AddDefaultMaterial(); Profiler.EndSample(); }
/// <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(GltfData data, UnityPath textureDirectory, ITextureDescriptorGenerator textureDescriptorGenerator, IReadOnlyDictionary <SubAssetKey, Texture> subAssets, Action <SubAssetKey, Texture2D> addRemap, Action <IEnumerable <UnityPath> > onCompleted = null) { var extractor = new TextureExtractor(data, textureDirectory, subAssets); foreach (var param in textureDescriptorGenerator.Get().GetEnumerable()) { extractor.Extract(param.SubAssetKey, param); } EditorApplication.delayCall += () => { // Wait for the texture assets to be imported foreach (var(key, targetPath) in extractor.Textures) { // remap var externalObject = targetPath.LoadAsset <Texture2D>(); #if VRM_DEVELOP // Debug.Log($"remap: {targetPath} => {externalObject}"); #endif if (externalObject != null) { addRemap(key, externalObject); } } if (onCompleted != null) { onCompleted(extractor.Textures.Values); } }; }
/// <summary> /// for export /// </summary> public Vrm10Storage() { m_data = new GltfData( string.Empty, string.Empty, GLTF, new List <GlbChunk>(),
public static (SubAssetKey, TextureDescriptor) CreateSRGB(GltfData data, int textureIndex, Vector2 offset, Vector2 scale) { var gltfTexture = data.GLTF.textures[textureIndex]; var gltfImage = data.GLTF.images[gltfTexture.source]; var name = TextureImportName.GetUnityObjectName(TextureImportTypes.sRGB, gltfTexture.name, gltfImage.uri); var sampler = TextureSamplerUtil.CreateSampler(data.GLTF, textureIndex); GetTextureBytesAsync getTextureBytesAsync = () => Task.FromResult(ToArray(data.GetImageBytesFromTextureIndex(textureIndex))); var param = new TextureDescriptor(name, gltfImage.GetExt(), gltfImage.uri, offset, scale, sampler, TextureImportTypes.sRGB, default, default, getTextureBytesAsync, default, default, default, default, default);
public void AccessorTest() { byte[] bytes = default; using (var ms = new MemoryStream()) using (var w = new BinaryWriter(ms)) { w.Write(1.0f); w.Write(2.0f); w.Write(3.0f); w.Write(4.0f); w.Write(5.0f); w.Write(6.0f); w.Write(7.0f); w.Write(8.0f); bytes = ms.ToArray(); } var gltf = new glTF { buffers = new List <glTFBuffer> { new glTFBuffer { } }, bufferViews = new List <glTFBufferView> { new glTFBufferView { buffer = 0, byteLength = 32, byteOffset = 0, } }, accessors = new List <glTFAccessor> { new glTFAccessor { bufferView = 0, componentType = glComponentType.FLOAT, count = 2, byteOffset = 0, type = "VEC4", } } }; using (var data = GltfData.CreateFromGltfDataForTest(gltf, new ArraySegment <byte>(bytes))) { var(getter, len) = WeightsAccessor.GetAccessor(data, 0); Assert.AreEqual((1.0f, 2.0f, 3.0f, 4.0f), getter(0)); Assert.AreEqual((5.0f, 6.0f, 7.0f, 8.0f), getter(1)); } }
public void DividedVertexBufferTest() { var data = new ExportingGltfData(50 * 1024 * 1024); var Materials = new List <Material> { new Material(Shader.Find("Standard")), // A new Material(Shader.Find("Standard")), // B }; var(go, mesh) = CreateMesh(Materials.ToArray()); var meshExportSettings = new GltfExportSettings { DivideVertexBuffer = true }; var axisInverter = Axes.X.Create(); var unityMesh = MeshExportList.Create(go); var(gltfMesh, blendShapeIndexMap) = meshExportSettings.DivideVertexBuffer ? MeshExporter_DividedVertexBuffer.Export(data, unityMesh, Materials, axisInverter, meshExportSettings) : MeshExporter_SharedVertexBuffer.Export(data, unityMesh, Materials, axisInverter, meshExportSettings) ; var parsed = GltfData.CreateFromGltfDataForTest(data.GLTF, data.BinBytes); { var indices = parsed.GetIndices(gltfMesh.primitives[0].indices); Assert.AreEqual(0, indices[0]); Assert.AreEqual(1, indices[1]); Assert.AreEqual(3, indices[2]); Assert.AreEqual(3, indices[3]); Assert.AreEqual(1, indices[4]); Assert.AreEqual(2, indices[5]); } { var positions = parsed.GetArrayFromAccessor <Vector3>(gltfMesh.primitives[0].attributes.POSITION); Assert.AreEqual(4, positions.Length); } { var indices = parsed.GetIndices(gltfMesh.primitives[1].indices); Assert.AreEqual(0, indices[0]); Assert.AreEqual(1, indices[1]); Assert.AreEqual(3, indices[2]); Assert.AreEqual(3, indices[3]); Assert.AreEqual(1, indices[4]); Assert.AreEqual(2, indices[5]); } { var positions = parsed.GetArrayFromAccessor <Vector3>(gltfMesh.primitives[1].attributes.POSITION); Assert.AreEqual(4, positions.Length); } }
public override void OnEnable() { base.OnEnable(); m_importer = target as ZipArchivedGltfScriptedImporter; m_data = new AutoGltfFileParser(m_importer.assetPath).Parse(); var materialGenerator = new GltfMaterialDescriptorGenerator(); var materialKeys = m_data.GLTF.materials.Select((_, i) => materialGenerator.Get(m_data, i).SubAssetKey); var textureKeys = new GltfTextureDescriptorGenerator(m_data).Get().GetEnumerable().Select(x => x.SubAssetKey); m_materialEditor = new RemapEditorMaterial(materialKeys.Concat(textureKeys), GetEditorMap, SetEditorMap); m_animationEditor = new RemapEditorAnimation(AnimationImporterUtil.EnumerateSubAssetKeys(m_data.GLTF), GetEditorMap, SetEditorMap); }
/// <summary> /// for import /// </summary> /// <param name="json"></param> /// <param name="bin"></param> public Vrm10ImportData(UniGLTF.GltfData data) { m_data = data; if (UniGLTF.Extensions.VRMC_vrm.GltfDeserializer.TryGet(Gltf.extensions, out UniGLTF.Extensions.VRMC_vrm.VRMC_vrm vrm)) { gltfVrm = vrm; } if (UniGLTF.Extensions.VRMC_springBone.GltfDeserializer.TryGet(Gltf.extensions, out UniGLTF.Extensions.VRMC_springBone.VRMC_springBone springBone)) { gltfVrmSpringBone = springBone; } }
public MaterialDescriptor Get(GltfData data, int i) { if (!GltfUnlitMaterialImporter.TryCreateParam(data, i, out var param)) { if (!GltfPbrMaterialImporter.TryCreateParam(data, i, out param)) { // fallback #if VRM_DEVELOP Debug.LogWarning($"material: {i} out of range. fallback"); #endif return(new MaterialDescriptor(GetMaterialName(i, null), GltfPbrMaterialImporter.ShaderName)); } } return(param); }
public static (Getter, int) GetAccessor(GltfData data, int accessorIndex) { var gltfAccessor = data.GLTF.accessors[accessorIndex]; switch (gltfAccessor.componentType) { case glComponentType.UNSIGNED_BYTE: { var array = data.GetArrayFromAccessor <Byte4>(accessorIndex); Getter getter = (i) => { var value = array[i]; return(value.x, value.y, value.z, value.w); }; return(getter, array.Length); }
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 data = new ExportingGltfData(); var gltf = data.GLTF; string json; using (var exporter = new gltfExporter(data, new GltfExportSettings())) { exporter.Prepare(go); exporter.Export(new EditorTextureSerializer()); json = gltf.ToJson(); } Assert.AreEqual(0, gltf.meshes.Count); Assert.AreEqual(1, gltf.nodes.Count); Assert.AreEqual(-1, gltf.nodes[0].mesh); // import { var parsed = GltfData.CreateFromExportForTest(data); using (var context = new ImporterContext(parsed)) using (var loaded = context.Load()) { Assert.AreEqual(1, loaded.transform.GetChildren().Count()); { var child = loaded.transform.GetChild(0); Assert.IsNull(child.GetSharedMesh()); } } } } finally { GameObject.DestroyImmediate(go); } }
private static Texture2D AssignTextureToMaterialPropertyAndExportAndExtract(Texture2D srcTex, string srcImageName, string propertyName) { // Prepare var root = GameObject.CreatePrimitive(PrimitiveType.Cube); var mat = new Material(Shader.Find("Standard")); mat.SetTexture(propertyName, srcTex); root.GetComponent <MeshRenderer>().sharedMaterial = mat; // Export glTF var data = new ExportingGltfData(); using (var exporter = new gltfExporter(data, new GltfExportSettings { InverseAxis = Axes.X, ExportOnlyBlendShapePosition = false, UseSparseAccessorForMorphTarget = false, DivideVertexBuffer = false, })) { exporter.Prepare(root); exporter.Export(new EditorTextureSerializer()); } var gltf = data.GLTF; Assert.AreEqual(1, gltf.images.Count); var exportedImage = gltf.images[0]; Assert.AreEqual("image/png", exportedImage.mimeType); Assert.AreEqual(srcImageName, exportedImage.name); UnityEngine.Object.DestroyImmediate(mat); UnityEngine.Object.DestroyImmediate(root); var parsed = GltfData.CreateFromGltfDataForTest(gltf, data.BinBytes); // Extract Image to Texture2D var exportedBytes = parsed.GetBytesFromBufferView(exportedImage.bufferView).ToArray(); var exportedTexture = new Texture2D(2, 2, TextureFormat.ARGB32, mipChain: false, linear: false); Assert.IsTrue(exportedTexture.LoadImage(exportedBytes)); // Always true ? Assert.AreEqual(srcTex.width, exportedTexture.width); Assert.AreEqual(srcTex.height, exportedTexture.height); return(exportedTexture); }
public static (SubAssetKey, TextureDescriptor) StandardTexture(GltfData data, 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) = GltfTextureImporter.GetTextureOffsetAndScale(src.pbrMetallicRoughness.metallicRoughnessTexture); return(GltfTextureImporter.CreateStandard(data, src.pbrMetallicRoughness?.metallicRoughnessTexture?.index, src.occlusionTexture?.index, offset, scale, metallicFactor, roughnessFactor)); }
public static void Extract(ScriptedImporter importer, GltfData data) { if (string.IsNullOrEmpty(importer.assetPath)) { return; } var path = GetAndCreateFolder(importer.assetPath, ".Animations"); foreach (var asset in AssetDatabase.LoadAllAssetsAtPath(importer.assetPath)) { if (asset is AnimationClip) { ExtractSubAsset(asset, $"{path}/{asset.name}.asset", false); } } AssetDatabase.ImportAsset(importer.assetPath, ImportAssetOptions.ForceUpdate); }
/// <summary> /// for export /// </summary> public Vrm10Storage() { m_data = new GltfData( string.Empty, string.Empty, new glTF { extensionsUsed = new List <string>(), }, new List <GlbChunk>(), new SimpleStorage(new ArraySegment <byte>()), new MigrationFlags() ); Buffers = new List <UniGLTF.IBytesBuffer>() { new UniGLTF.ArrayByteBuffer() }; Gltf.AddBuffer(Buffers[0]); }
public static (Getter, int) GetAccessor(GltfData data, int accessorIndex) { var gltfAccessor = data.GLTF.accessors[accessorIndex]; switch (gltfAccessor.componentType) { case glComponentType.UNSIGNED_BYTE: { var array = data.GetArrayFromAccessor <Byte4>(accessorIndex); Getter getter = (i) => { var value = array[i]; var inv = 1.0f / byte.MaxValue; return(value.x * inv, value.y *inv, value.z *inv, value.w *inv); }; return(getter, array.Length); } case glComponentType.UNSIGNED_SHORT: { var array = data.GetArrayFromAccessor <UShort4>(accessorIndex); Getter getter = (i) => { var value = array[i]; var inv = 1.0f / ushort.MaxValue; return(value.x * inv, value.y *inv, value.z *inv, value.w *inv); }; return(getter, array.Length); } case glComponentType.FLOAT: { var array = data.GetArrayFromAccessor <Vector4>(accessorIndex); Getter getter = (i) => { var value = array[i]; return(value.x, value.y, value.z, value.w); }; return(getter, array.Length); } }
public static NativeArray <Color>?GetColors(this glTFPrimitives primitives, GltfData data, int positionsLength) { if (!HasColor(primitives)) { return(null); } switch (data.GLTF.accessors[primitives.attributes.COLOR_0].TypeCount) { case 3: { var vec3Color = data.GetArrayFromAccessor <Vector3>(primitives.attributes.COLOR_0); if (vec3Color.Length != positionsLength) { throw new Exception("different length"); } var colors = data.NativeArrayManager.CreateNativeArray <Color>(vec3Color.Length); for (var index = 0; index < vec3Color.Length; index++) { var color = vec3Color[index]; colors[index] = new Color(color.x, color.y, color.z); } return(colors); } case 4: var result = data.GetArrayFromAccessor <Color>(primitives.attributes.COLOR_0); if (result.Length != positionsLength) { throw new Exception("different length"); } return(result); default: throw new NotImplementedException( $"unknown color type {data.GLTF.accessors[primitives.attributes.COLOR_0].type}"); } }
static void RuntimeLoadExport(FileInfo gltf, int subStrStart) { GltfData data = null; try { data = new AutoGltfFileParser(gltf.FullName).Parse(); } catch (Exception ex) { Debug.LogError($"ParseError: {gltf}"); Debug.LogException(ex); } using (data) using (var loader = new ImporterContext(data)) { try { var loaded = loader.Load(); if (loaded == null) { Debug.LogWarning($"root is null: ${gltf}"); return; } if (Skip.Contains(gltf.Directory.Parent.Name)) { // Export issue: // skip return; } Export(loaded.gameObject); } catch (Exception ex) { Message(gltf.FullName.Substring(subStrStart), ex); } } }
/// <summary> /// for import /// </summary> /// <param name="json"></param> /// <param name="bin"></param> public Vrm10Storage(UniGLTF.GltfData data) { m_data = data; if (UniGLTF.Extensions.VRMC_vrm.GltfDeserializer.TryGet(Gltf.extensions, out UniGLTF.Extensions.VRMC_vrm.VRMC_vrm vrm)) { gltfVrm = vrm; } if (UniGLTF.Extensions.VRMC_springBone.GltfDeserializer.TryGet(Gltf.extensions, out UniGLTF.Extensions.VRMC_springBone.VRMC_springBone springBone)) { gltfVrmSpringBone = springBone; } Buffers = new List <UniGLTF.IBytesBuffer>() { Gltf.buffers[0].Buffer, }; }
public static (int VertexCapacity, int IndexCapacity) GetCapacity(GltfData data, glTFMesh gltfMesh) { var vertexCount = 0; var indexCount = 0; foreach (var primitive in gltfMesh.primitives) { var positions = data.GLTF.accessors[primitive.attributes.POSITION]; vertexCount += positions.count; if (primitive.indices == -1) { indexCount += positions.count; } else { var accessor = data.GLTF.accessors[primitive.indices]; indexCount += accessor.count; } } return(vertexCount, indexCount); }
void ExtractMaterialsAndTextures(ScriptedImporter self, GltfData data, ITextureDescriptorGenerator textureDescriptorGenerator, 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 = _ => { // texture extract 後に importer 発動 AssetDatabase.ImportAsset(self.assetPath, ImportAssetOptions.ForceUpdate); ExtractMaterials(self, materialDir); }; // subAsset を ExternalObject として投入する var subAssets = AssetDatabase.LoadAllAssetsAtPath(self.assetPath) .Select(x => x as Texture) .Where(x => x != null) .Select(x => (new SubAssetKey(x), x)) .ToDictionary(kv => kv.Item1, kv => kv.Item2) ; var assetPath = UnityPath.FromUnityPath(self.assetPath); var dirName = textureDir(assetPath.Value); // $"{assetPath.FileNameWithoutExtension}.Textures"; TextureExtractor.ExtractTextures( data, assetPath.Parent.Child(dirName), textureDescriptorGenerator, subAssets, addRemap, onCompleted ); }
public ImporterContext( GltfData data, IReadOnlyDictionary <SubAssetKey, UnityEngine.Object> externalObjectMap = null, ITextureDeserializer textureDeserializer = null) { Data = data; TextureDescriptorGenerator = new GltfTextureDescriptorGenerator(Data); MaterialDescriptorGenerator = new GltfMaterialDescriptorGenerator(); ExternalObjectMap = externalObjectMap ?? new Dictionary <SubAssetKey, UnityEngine.Object>(); textureDeserializer = textureDeserializer ?? new UnityTextureDeserializer(); TextureFactory = new TextureFactory(textureDeserializer, ExternalObjectMap .Where(x => x.Value is Texture) .ToDictionary(x => x.Key, x => (Texture)x.Value), Data.MigrationFlags.IsRoughnessTextureValueSquared); MaterialFactory = new MaterialFactory(ExternalObjectMap .Where(x => x.Value is Material) .ToDictionary(x => x.Key, x => (Material)x.Value)); AnimationClipFactory = new AnimationClipFactory(ExternalObjectMap .Where(x => x.Value is AnimationClip) .ToDictionary(x => x.Key, x => (AnimationClip)x.Value)); }
internal MeshContext ReadMesh(GltfData data, int meshIndex, IAxisInverter inverter) { Profiler.BeginSample("ReadMesh"); var gltfMesh = data.GLTF.meshes[meshIndex]; var meshContext = new MeshContext(gltfMesh.name, meshIndex); if (HasSharedVertexBuffer(gltfMesh)) { meshContext.ImportMeshSharingVertexBuffer(data, gltfMesh, inverter); } else { meshContext.ImportMeshIndependentVertexBuffer(data, gltfMesh, inverter); } meshContext.RenameBlendShape(gltfMesh); meshContext.DropUnusedVertices(); Profiler.EndSample(); return(meshContext); }
public void OnGUI(ScriptedImporter importer, GltfData data, ITextureDescriptorGenerator textureDescriptorGenerator, Func <string, string> textureDir, Func <string, string> materialDir) { if (CanExtract(importer)) { if (GUILayout.Button("Extract Materials And Textures ...")) { ExtractMaterialsAndTextures(importer, data, textureDescriptorGenerator, textureDir, materialDir); } EditorGUILayout.HelpBox("Extract subasset to external object and overwrite remap", MessageType.Info); } else { if (GUILayout.Button("Clear extraction")) { ClearExternalObjects(importer, typeof(Texture), typeof(Material)); } EditorGUILayout.HelpBox("Clear remap. All remap use subAsset", MessageType.Info); } // // Draw ExternalObjectMap // s_foldMaterials = EditorGUILayout.Foldout(s_foldMaterials, "Remapped Materials"); if (s_foldMaterials) { DrawRemapGUI <UnityEngine.Material>(importer.GetExternalObjectMap()); } s_foldTextures = EditorGUILayout.Foldout(s_foldTextures, "Remapped Textures"); if (s_foldTextures) { DrawRemapGUI <UnityEngine.Texture>(importer.GetExternalObjectMap()); } }