diff --git a/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/GltfScriptedImporterBase.cs b/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/GltfScriptedImporterBase.cs index 4637c4ecb..d7588cbcf 100644 --- a/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/GltfScriptedImporterBase.cs +++ b/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/GltfScriptedImporterBase.cs @@ -19,35 +19,7 @@ namespace UniGLTF public ScriptedImporterAxes m_reverseAxis = default; [SerializeField] - [Header("Experimental")] - public RenderPipelineTypes m_renderPipeline; - - void OnValidate() - { - if (m_renderPipeline == UniGLTF.RenderPipelineTypes.UniversalRenderPipeline) - { - if (Shader.Find(UniGLTF.UrpGltfPbrMaterialImporter.ShaderName) == null) - { - Debug.LogWarning("URP is not installed. Force to BuiltinRenderPipeline"); - m_renderPipeline = UniGLTF.RenderPipelineTypes.BuiltinRenderPipeline; - } - } - } - - static IMaterialDescriptorGenerator GetMaterialGenerator(RenderPipelineTypes renderPipeline) - { - switch (renderPipeline) - { - case RenderPipelineTypes.BuiltinRenderPipeline: - return new BuiltInGltfMaterialDescriptorGenerator(); - - case RenderPipelineTypes.UniversalRenderPipeline: - return new UrpGltfMaterialDescriptorGenerator(); - - default: - throw new System.NotImplementedException(); - } - } + public ImporterRenderPipelineTypes m_renderPipeline; /// /// glb をパースして、UnityObject化、さらにAsset化する @@ -55,7 +27,8 @@ namespace UniGLTF /// /// /// - protected static void Import(ScriptedImporter scriptedImporter, AssetImportContext context, Axes reverseAxis, RenderPipelineTypes renderPipeline) + /// + protected static void Import(ScriptedImporter scriptedImporter, AssetImportContext context, Axes reverseAxis, ImporterRenderPipelineTypes renderPipeline) { UniGLTFLogger.Log("OnImportAsset to " + scriptedImporter.assetPath); @@ -68,10 +41,11 @@ namespace UniGLTF .Where(x => x.Value != null) .ToDictionary(kv => new SubAssetKey(kv.Value.GetType(), kv.Key.name), kv => kv.Value); - IMaterialDescriptorGenerator materialGenerator = GetMaterialGenerator(renderPipeline); + var materialGenerator = GetMaterialDescriptorGenerator(renderPipeline); + var importerContextSettings = new ImporterContextSettings(loadAnimation: true, invertAxis: reverseAxis); using (var data = new AutoGltfFileParser(scriptedImporter.assetPath).Parse()) - using (var loader = new ImporterContext(data, extractedObjects, materialGenerator: materialGenerator)) + using (var loader = new ImporterContext(data, extractedObjects, materialGenerator: materialGenerator, settings: importerContextSettings)) { // Configure TextureImporter to Extracted Textures. foreach (var textureInfo in loader.TextureDescriptorGenerator.Get().GetEnumerable()) @@ -79,7 +53,6 @@ namespace UniGLTF TextureImporterConfigurator.Configure(textureInfo, loader.TextureFactory.ExternalTextures); } - loader.InvertAxis = reverseAxis; var loaded = loader.Load(); loaded.ShowMeshes(); @@ -94,5 +67,16 @@ namespace UniGLTF context.SetMainObject(root); } } + + private static IMaterialDescriptorGenerator GetMaterialDescriptorGenerator(ImporterRenderPipelineTypes renderPipeline) + { + return renderPipeline switch + { + ImporterRenderPipelineTypes.Auto => MaterialDescriptorGeneratorUtility .GetValidGltfMaterialDescriptorGenerator(), + ImporterRenderPipelineTypes.BuiltinRenderPipeline => MaterialDescriptorGeneratorUtility .GetGltfMaterialDescriptorGenerator(RenderPipelineTypes.BuiltinRenderPipeline), + ImporterRenderPipelineTypes.UniversalRenderPipeline => MaterialDescriptorGeneratorUtility .GetGltfMaterialDescriptorGenerator(RenderPipelineTypes.UniversalRenderPipeline), + _ => MaterialDescriptorGeneratorUtility.GetValidGltfMaterialDescriptorGenerator(), + }; + } } } diff --git a/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/ImporterRenderPipelineTypes.cs b/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/ImporterRenderPipelineTypes.cs new file mode 100644 index 000000000..0acad15f1 --- /dev/null +++ b/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/ImporterRenderPipelineTypes.cs @@ -0,0 +1,9 @@ +namespace UniGLTF +{ + public enum ImporterRenderPipelineTypes + { + Auto = 0, + BuiltinRenderPipeline = 1, + UniversalRenderPipeline = 2, + } +} \ No newline at end of file diff --git a/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/ImporterRenderPipelineTypes.cs.meta b/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/ImporterRenderPipelineTypes.cs.meta new file mode 100644 index 000000000..fcc3507a5 --- /dev/null +++ b/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/ImporterRenderPipelineTypes.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: d4f38213d6e442ef986fd3e633991ba7 +timeCreated: 1722347490 \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/ExportingGltfData.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/ExportingGltfData.cs index 1788c7cd1..08883cb89 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/ExportingGltfData.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/ExportingGltfData.cs @@ -145,6 +145,7 @@ namespace UniGLTF public int AppendToBuffer(NativeArray segment) { var gltfBufferView = _buffer.Extend(segment); + Gltf.buffers[0].byteLength = _buffer.Bytes.Count; var viewIndex = Gltf.bufferViews.Count; Gltf.bufferViews.Add(gltfBufferView); return viewIndex; diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs index d7c56f709..131bf0695 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs @@ -12,12 +12,14 @@ namespace UniGLTF /// public class ImporterContext : IResponsibilityForDestroyObjects { + private readonly ImporterContextSettings _settings; + public ITextureDescriptorGenerator TextureDescriptorGenerator { get; protected set; } public IMaterialDescriptorGenerator MaterialDescriptorGenerator { get; protected set; } public TextureFactory TextureFactory { get; } public MaterialFactory MaterialFactory { get; } public AnimationClipFactory AnimationClipFactory { get; } - public bool LoadAnimation { get; set; } = true; + private bool LoadAnimation => _settings.LoadAnimation; public IReadOnlyDictionary ExternalObjectMap; @@ -29,12 +31,15 @@ namespace UniGLTF /// 外部オブジェクトのリスト(主にScriptedImporterのRemapで使う) /// Textureロードをカスタマイズする /// Materialロードをカスタマイズする(URP向け) + /// ImporterContextの設定 public ImporterContext( GltfData data, IReadOnlyDictionary externalObjectMap = null, ITextureDeserializer textureDeserializer = null, - IMaterialDescriptorGenerator materialGenerator = null) + IMaterialDescriptorGenerator materialGenerator = null, + ImporterContextSettings settings = null) { + _settings = settings ?? new ImporterContextSettings(); Data = data; TextureDescriptorGenerator = new GltfTextureDescriptorGenerator(Data); MaterialDescriptorGenerator = materialGenerator ?? MaterialDescriptorGeneratorUtility.GetValidGltfMaterialDescriptorGenerator(); @@ -66,7 +71,7 @@ namespace UniGLTF /// /// GLTF から Unity に変換するときに反転させる軸 /// - public Axes InvertAxis = Axes.Z; + private Axes InvertAxis => _settings.InvertAxis; public static List UnsupportedExtensions = new List { diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContextSettings.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContextSettings.cs new file mode 100644 index 000000000..262a71719 --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContextSettings.cs @@ -0,0 +1,19 @@ +namespace UniGLTF +{ + public class ImporterContextSettings + { + public bool LoadAnimation { get; } + public Axes InvertAxis { get; } + + /// + /// ImporterContextの設定を指定する。 + /// + /// アニメーションをインポートする場合はtrueを指定(初期値はtrue) + /// GLTF から Unity に変換するときに反転させる軸を指定(初期値はAxes.Z) + public ImporterContextSettings(bool loadAnimation = true, Axes invertAxis = Axes.Z) + { + LoadAnimation = loadAnimation; + InvertAxis = invertAxis; + } + } +} \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContextSettings.cs.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContextSettings.cs.meta new file mode 100644 index 000000000..b57676d9a --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContextSettings.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 091d1bfaecd542b6a039fb7a3e3676f8 +timeCreated: 1723863327 \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/BuiltInRP/Import/BuiltInGltfMaterialDescriptorGenerator.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/BuiltInRP/Import/BuiltInGltfMaterialDescriptorGenerator.cs index eda109fb4..03ffca198 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/BuiltInRP/Import/BuiltInGltfMaterialDescriptorGenerator.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/BuiltInRP/Import/BuiltInGltfMaterialDescriptorGenerator.cs @@ -13,26 +13,15 @@ namespace UniGLTF { if (BuiltInGltfUnlitMaterialImporter.TryCreateParam(data, i, out var param)) return param; if (BuiltInGltfPbrMaterialImporter.TryCreateParam(data, i, out param)) return param; + // fallback if (Symbols.VRM_DEVELOP) { Debug.LogWarning($"material: {i} out of range. fallback"); } - - return new MaterialDescriptor( - GltfMaterialImportUtils.ImportMaterialName(i, null), - BuiltInGltfPbrMaterialImporter.Shader, - null, - new Dictionary(), - new Dictionary(), - new Dictionary(), - new Dictionary(), - new Action[]{}); + return GetGltfDefault(GltfMaterialImportUtils.ImportMaterialName(i, null)); } - public MaterialDescriptor GetGltfDefault() - { - return BuiltInGltfDefaultMaterialImporter.CreateParam(); - } + public MaterialDescriptor GetGltfDefault(string materialName = null) => BuiltInGltfDefaultMaterialImporter.CreateParam(materialName); } } diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/BuiltInRP/Import/Materials/BuiltInGltfDefaultMaterialImporter.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/BuiltInRP/Import/Materials/BuiltInGltfDefaultMaterialImporter.cs index b59d94bc7..c6f8112d8 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/BuiltInRP/Import/Materials/BuiltInGltfDefaultMaterialImporter.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/BuiltInRP/Import/Materials/BuiltInGltfDefaultMaterialImporter.cs @@ -9,11 +9,11 @@ namespace UniGLTF /// public static class BuiltInGltfDefaultMaterialImporter { - public static MaterialDescriptor CreateParam() + public static MaterialDescriptor CreateParam(string materialName = null) { // FIXME return new MaterialDescriptor( - "__default__", + string.IsNullOrEmpty(materialName) ? "__default__" : materialName, BuiltInGltfPbrMaterialImporter.Shader, default, new Dictionary(), diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/Export/GltfMaterialExportUtils.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/Export/GltfMaterialExportUtils.cs index 22da6e790..74b068a1d 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/Export/GltfMaterialExportUtils.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/Export/GltfMaterialExportUtils.cs @@ -7,10 +7,19 @@ namespace UniGLTF { public static void ExportTextureTransform(Material src, glTFTextureInfo dstTextureInfo, string targetTextureName) { - if (dstTextureInfo != null && src.HasProperty(targetTextureName)) + if (src.HasProperty(targetTextureName)) { var offset = src.GetTextureOffset(targetTextureName); var scale = src.GetTextureScale(targetTextureName); + + ExportTextureTransform(offset, scale, dstTextureInfo); + } + } + + public static void ExportTextureTransform(Vector2 offset, Vector2 scale, glTFTextureInfo dstTextureInfo) + { + if (dstTextureInfo != null) + { (scale, offset) = TextureTransform.VerticalFlipScaleOffset(scale, offset); glTF_KHR_texture_transform.Serialize(dstTextureInfo, (offset.x, offset.y), (scale.x, scale.y)); diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/Export/MaterialExporterUtility.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/Export/MaterialExporterUtility.cs index 449e9f735..3ddfca93a 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/Export/MaterialExporterUtility.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/Export/MaterialExporterUtility.cs @@ -6,7 +6,7 @@ { return RenderPipelineUtility.GetRenderPipelineType() switch { - RenderPipelineTypes.UniversalRenderPipeline => throw new System.NotImplementedException(), + RenderPipelineTypes.UniversalRenderPipeline => new UrpGltfMaterialExporter(), RenderPipelineTypes.BuiltinRenderPipeline => new BuiltInGltfMaterialExporter(), _ => new BuiltInGltfMaterialExporter(), }; diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/Import/IMaterialDescriptorGenerator.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/Import/IMaterialDescriptorGenerator.cs index 522cc3e56..6ba99e4d2 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/Import/IMaterialDescriptorGenerator.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/Import/IMaterialDescriptorGenerator.cs @@ -14,6 +14,6 @@ /// /// Generate the MaterialDescriptor for the non-specified glTF material. /// - MaterialDescriptor GetGltfDefault(); + MaterialDescriptor GetGltfDefault(string materialName = null); } } diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/Import/MaterialDescriptor.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/Import/MaterialDescriptor.cs index 131181bea..f33d6a37a 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/Import/MaterialDescriptor.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/Import/MaterialDescriptor.cs @@ -1,11 +1,14 @@ using System; using System.Collections.Generic; +using System.Threading.Tasks; using UnityEngine; namespace UniGLTF { public sealed class MaterialDescriptor { + public delegate Task MaterialGenerateAsyncFunc(Material m, GetTextureAsyncFunc getTexture, IAwaitCaller awaitCaller); + public readonly string Name; public readonly Shader Shader; public readonly int? RenderQueue; @@ -14,6 +17,7 @@ namespace UniGLTF public readonly IReadOnlyDictionary Colors; public readonly IReadOnlyDictionary Vectors; public readonly IReadOnlyList> Actions; + public readonly IReadOnlyList AsyncActions; public SubAssetKey SubAssetKey => new SubAssetKey(SubAssetKey.MaterialType, Name); @@ -25,7 +29,8 @@ namespace UniGLTF IReadOnlyDictionary floatValues, IReadOnlyDictionary colors, IReadOnlyDictionary vectors, - IReadOnlyList> actions) + IReadOnlyList> actions, + IReadOnlyList asyncActions = null) { Name = name; Shader = shader; @@ -35,6 +40,7 @@ namespace UniGLTF Colors = colors; Vectors = vectors; Actions = actions; + AsyncActions = asyncActions ?? new List(); } } } \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/Import/MaterialDescriptorGeneratorUtility.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/Import/MaterialDescriptorGeneratorUtility.cs index dee8cba3d..97dda7c77 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/Import/MaterialDescriptorGeneratorUtility.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/Import/MaterialDescriptorGeneratorUtility.cs @@ -4,7 +4,12 @@ namespace UniGLTF { public static IMaterialDescriptorGenerator GetValidGltfMaterialDescriptorGenerator() { - return RenderPipelineUtility.GetRenderPipelineType() switch + return GetGltfMaterialDescriptorGenerator(RenderPipelineUtility.GetRenderPipelineType()); + } + + public static IMaterialDescriptorGenerator GetGltfMaterialDescriptorGenerator(RenderPipelineTypes renderPipelineType) + { + return renderPipelineType switch { RenderPipelineTypes.UniversalRenderPipeline => new UrpGltfMaterialDescriptorGenerator(), RenderPipelineTypes.BuiltinRenderPipeline => new BuiltInGltfMaterialDescriptorGenerator(), diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/Import/MaterialFactory.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/Import/MaterialFactory.cs index ccf38deb0..ab4d0955b 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/Import/MaterialFactory.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/Import/MaterialFactory.cs @@ -10,11 +10,9 @@ namespace UniGLTF public class MaterialFactory : IResponsibilityForDestroyObjects { private readonly IReadOnlyDictionary m_externalMap; - - /// - /// デフォルトマテリアルの MaterialDescriptor は IMaterialDescriptorGenerator の実装によって異なるので外から渡す - /// + private readonly SubAssetKey m_defaultMaterialKey = new SubAssetKey(typeof(Material), "__UNIGLTF__DEFAULT__MATERIAL__"); private readonly MaterialDescriptor m_defaultMaterialParams; + private readonly List m_materials = new List(); /// /// gltfPritmitive.material が無い場合のデフォルトマテリアル @@ -23,6 +21,9 @@ namespace UniGLTF /// private Material m_defaultMaterial; + public IReadOnlyList Materials => m_materials; + + public MaterialFactory(IReadOnlyDictionary externalMaterialMap, MaterialDescriptor defaultMaterialParams) { m_externalMap = externalMaterialMap; @@ -45,18 +46,6 @@ namespace UniGLTF } } - List m_materials = new List(); - public IReadOnlyList Materials => m_materials; - void Remove(Material material) - { - var index = m_materials.FindIndex(x => x.Asset == material); - if (index >= 0) - { - m_materials.RemoveAt(index); - - } - } - public void Dispose() { foreach (var x in m_materials) @@ -67,6 +56,11 @@ namespace UniGLTF UnityObjectDestroyer.DestroyRuntimeOrEditor(x.Asset); } } + + if (m_defaultMaterial != null) + { + UnityObjectDestroyer.DestroyRuntimeOrEditor(m_defaultMaterial); + } } /// @@ -90,6 +84,12 @@ namespace UniGLTF m_materials.Remove(x); } } + + if (m_defaultMaterial != null) + { + take(m_defaultMaterialKey, m_defaultMaterial); + m_defaultMaterial = null; + } } public Material GetMaterial(int index) @@ -101,6 +101,12 @@ namespace UniGLTF public async Task GetDefaultMaterialAsync(IAwaitCaller awaitCaller) { + if (m_externalMap.ContainsKey(m_defaultMaterialKey)) + { + m_defaultMaterial = m_externalMap[m_defaultMaterialKey]; + return m_externalMap[m_defaultMaterialKey]; + } + if (m_defaultMaterial == null) { m_defaultMaterial = await LoadAsync(m_defaultMaterialParams, (_, _) => null, awaitCaller); @@ -136,7 +142,8 @@ namespace UniGLTF if (texture != null) { material.SetTexture(kv.Key, texture); - SetTextureOffsetAndScale(material, kv.Key, kv.Value.Offset, kv.Value.Scale); + material.SetTextureOffset(kv.Key, kv.Value.Offset); + material.SetTextureScale(kv.Key, kv.Value.Scale); } } @@ -165,15 +172,14 @@ namespace UniGLTF action(material); } + foreach (var asyncAction in matDesc.AsyncActions) + { + await asyncAction(material, getTexture, awaitCaller); + } + m_materials.Add(new MaterialLoadInfo(matDesc.SubAssetKey, material, false)); return material; } - - public static void SetTextureOffsetAndScale(Material material, string propertyName, Vector2 offset, Vector2 scale) - { - material.SetTextureOffset(propertyName, offset); - material.SetTextureScale(propertyName, scale); - } } } diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/Export.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/Export.meta new file mode 100644 index 000000000..758ce0a7e --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/Export.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 4c2edd284a744a13bf888a4b29fac93a +timeCreated: 1722269836 \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/Export/Materials.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/Export/Materials.meta new file mode 100644 index 000000000..4fe19bda2 --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/Export/Materials.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 70546771aa234567b5d7c4430548ac0f +timeCreated: 1722269920 \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/Export/Materials/UrpFallbackMaterialExporter.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/Export/Materials/UrpFallbackMaterialExporter.cs new file mode 100644 index 000000000..c590d4e93 --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/Export/Materials/UrpFallbackMaterialExporter.cs @@ -0,0 +1,36 @@ +using System; +using UnityEngine; + +namespace UniGLTF +{ + /// + /// フォールバック目的で最低限なにかをエクスポートする。 + /// + /// メインカラーとメインテクスチャをエクスポートする。 + /// + public class UrpFallbackMaterialExporter + { + public glTFMaterial ExportMaterial(Material src, ITextureExporter textureExporter) + { + var dst = new glTFMaterial + { + name = src.name, + pbrMetallicRoughness = new glTFPbrMetallicRoughness(), + }; + + dst.pbrMetallicRoughness.baseColorFactor = src.color.ToFloat4(ColorSpace.sRGB, ColorSpace.Linear); + var index = textureExporter.RegisterExportingAsSRgb(src.mainTexture, false); + if (index >= 0) + { + dst.pbrMetallicRoughness.baseColorTexture = new glTFMaterialBaseColorTextureInfo + { + index = index, + texCoord = 0, + }; + GltfMaterialExportUtils.ExportTextureTransform(src.mainTextureOffset, src.mainTextureScale, dst.pbrMetallicRoughness.baseColorTexture); + } + + return dst; + } + } +} \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/Export/Materials/UrpFallbackMaterialExporter.cs.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/Export/Materials/UrpFallbackMaterialExporter.cs.meta new file mode 100644 index 000000000..908fd8446 --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/Export/Materials/UrpFallbackMaterialExporter.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: c0269be076674f5988895ecd61b8d316 +timeCreated: 1722612454 \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/Export/Materials/UrpLitMaterialExporter.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/Export/Materials/UrpLitMaterialExporter.cs new file mode 100644 index 000000000..3ae4807ee --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/Export/Materials/UrpLitMaterialExporter.cs @@ -0,0 +1,239 @@ +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.Rendering; + +namespace UniGLTF +{ + public class UrpLitMaterialExporter + { + public Shader Shader { get; set; } + + /// + /// "Universal Render Pipeline/Lit" シェーダのマテリアルをエクスポートする。 + /// + /// プロパティに互換性がある他のシェーダを指定することもできる。 + /// + public UrpLitMaterialExporter(Shader shader = null) + { + Shader = shader != null ? shader : Shader.Find("Universal Render Pipeline/Lit"); + } + + public bool TryExportMaterial(Material src, ITextureExporter textureExporter, out glTFMaterial dst) + { + try + { + if (src == null) throw new ArgumentNullException(nameof(src)); + if (textureExporter == null) throw new ArgumentNullException(nameof(textureExporter)); + if (src.shader != Shader || Shader == null) throw new UniGLTFShaderNotMatchedInternalException(src.shader); + + dst = new glTFMaterial + { + name = src.name, + pbrMetallicRoughness = new glTFPbrMetallicRoughness(), + }; + + var context = new UrpLitContext(src); + foreach (var validation in EnumerateValidation(context)) + { + if (!validation.CanExport) + { + Debug.LogError(validation.Message, src); + throw new UniGLTFNotSupportedException(validation.Message); + } + } + + ExportSurfaceSettings(context, dst, textureExporter); + ExportBaseColor(context, dst, textureExporter); + ExportMetallicSmoothness(context, dst, textureExporter); + ExportOcclusion(context, dst, textureExporter); + ExportNormal(context, dst, textureExporter); + ExportEmission(context, dst, textureExporter); + + return true; + } + catch (UniGLTFShaderNotMatchedInternalException) + { + dst = default; + return false; + } + catch (Exception e) + { + Debug.LogException(e); + dst = default; + return false; + } + } + + public static void ExportSurfaceSettings(UrpBaseShaderContext context, glTFMaterial dst, ITextureExporter textureExporter) + { + dst.alphaMode = (context.SurfaceType, context.IsAlphaClipEnabled) switch + { + (UrpLitSurfaceType.Opaque, false) => glTFBlendMode.OPAQUE.ToString(), + (UrpLitSurfaceType.Opaque, true) => glTFBlendMode.MASK.ToString(), + (UrpLitSurfaceType.Transparent, false) => glTFBlendMode.BLEND.ToString(), + (UrpLitSurfaceType.Transparent, true) => glTFBlendMode.BLEND.ToString(), // NOTE: not supported in glTF + _ => throw new ArgumentOutOfRangeException() + }; + dst.alphaCutoff = context.Cutoff; + dst.doubleSided = context.CullMode != CullMode.Back; // NOTE: cull front not supported in glTF + } + + public static void ExportBaseColor(UrpBaseShaderContext context, glTFMaterial dst, ITextureExporter textureExporter) + { + dst.pbrMetallicRoughness.baseColorFactor = context.BaseColorSrgb.ToFloat4(ColorSpace.sRGB, ColorSpace.Linear); + if (context.BaseTexture != null) + { + var needsAlpha = context.SurfaceType != UrpLitSurfaceType.Opaque; + var index = textureExporter.RegisterExportingAsSRgb(context.BaseTexture, needsAlpha); + if (index >= 0) + { + dst.pbrMetallicRoughness.baseColorTexture = new glTFMaterialBaseColorTextureInfo + { + index = index, + texCoord = 0, + }; + ExportBaseTexTransform(context, dst.pbrMetallicRoughness.baseColorTexture); + } + } + } + + public static void ExportMetallicSmoothness(UrpLitContext context, glTFMaterial dst, ITextureExporter textureExporter) + { + // NOTE: maybe KHR_materials_specular + if (context.WorkflowType != UrpLitWorkflowType.Metallic) return; + + // Metallic-Roughness + dst.pbrMetallicRoughness.metallicRoughnessTexture = null; + dst.pbrMetallicRoughness.metallicFactor = context.Metallic; + dst.pbrMetallicRoughness.roughnessFactor = 1.0f - context.Smoothness; + if (context.MetallicGlossMap != null) + { + var index = textureExporter.RegisterExportingAsCombinedGltfPbrParameterTextureFromUnityStandardTextures( + context.MetallicGlossMap, + context.Smoothness, + context.OcclusionTexture + ); + if (index >= 0) + { + dst.pbrMetallicRoughness.metallicRoughnessTexture = new glTFMaterialMetallicRoughnessTextureInfo + { + index = index, + texCoord = 0, + }; + ExportBaseTexTransform(context, dst.pbrMetallicRoughness.metallicRoughnessTexture); + dst.pbrMetallicRoughness.metallicFactor = 1.0f; + dst.pbrMetallicRoughness.roughnessFactor = 1.0f; + } + } + } + + public void ExportOcclusion(UrpLitContext context, glTFMaterial dst, ITextureExporter textureExporter) + { + if (context.WorkflowType != UrpLitWorkflowType.Metallic) return; + + // Occlusion + if (context.OcclusionTexture != null) + { + var index = textureExporter.RegisterExportingAsCombinedGltfPbrParameterTextureFromUnityStandardTextures( + context.MetallicGlossMap, + context.Smoothness, + context.OcclusionTexture + ); + if (index >= 0) + { + dst.occlusionTexture = new glTFMaterialOcclusionTextureInfo + { + index = index, + texCoord = 0, + strength = context.OcclusionStrength, + }; + ExportBaseTexTransform(context, dst.occlusionTexture); + } + } + } + + public void ExportNormal(UrpLitContext context, glTFMaterial dst, ITextureExporter textureExporter) + { + if (context.BumpMap == null) return; + + var index = textureExporter.RegisterExportingAsNormal(context.BumpMap); + if (index >= 0) + { + dst.normalTexture = new glTFMaterialNormalTextureInfo + { + index = index, + texCoord = 0, + scale = context.BumpScale, + }; + ExportBaseTexTransform(context, dst.normalTexture); + } + } + + public void ExportEmission(UrpLitContext context, glTFMaterial dst, ITextureExporter textureExporter) + { + if (!context.IsEmissionEnabled) return; + + dst.emissiveFactor = context.EmissionColorLinear.ToFloat3(ColorSpace.Linear, ColorSpace.Linear); + if (context.EmissionTexture != null) + { + var index = textureExporter.RegisterExportingAsSRgb(context.EmissionTexture, true); + if (index >= 0) + { + dst.emissiveTexture = new glTFMaterialEmissiveTextureInfo + { + index = index, + texCoord = 0, + }; + ExportBaseTexTransform(context, dst.emissiveTexture); + } + } + } + + private static void ExportBaseTexTransform(UrpBaseShaderContext context, glTFTextureInfo dst) + { + GltfMaterialExportUtils.ExportTextureTransform( + context.BaseTextureOffset, + context.BaseTextureScale, + dst + ); + } + + public static IEnumerable EnumerateValidation(UrpLitContext context) + { + var validationContext = ValidationContext.Create(context.Material); + + // Surface Settings + if (context.WorkflowType != UrpLitWorkflowType.Metallic) yield return Error(ValidationMessage.WorkflowTypeNotSupported); + if (context.SurfaceType == UrpLitSurfaceType.Transparent && context.IsAlphaClipEnabled) yield return Warning(ValidationMessage.TransparentAlphaClipNotSupported); + if (context.CullMode == CullMode.Front) yield return Error(ValidationMessage.BackFaceRenderingNotSupported); + if (context.BlendMode == UrpLitBlendMode.Additive) yield return Error(ValidationMessage.AdditiveBlendModeNotSupported); + if (context.BlendMode == UrpLitBlendMode.Multiply) yield return Error(ValidationMessage.MultiplyBlendModeNotSupported); + + // Etc Textures + if (context.ParallaxTexture != null) yield return Warning(ValidationMessage.ParallaxTextureNotSupported); + + yield break; + + Validation Error(ValidationMessage message) + { + return Validation.Error(message.ToString(), validationContext); + } + + Validation Warning(ValidationMessage message) + { + return Validation.Warning(message.ToString(), validationContext); + } + } + + public enum ValidationMessage + { + WorkflowTypeNotSupported, + TransparentAlphaClipNotSupported, + BackFaceRenderingNotSupported, + ParallaxTextureNotSupported, + AdditiveBlendModeNotSupported, + MultiplyBlendModeNotSupported, + } + } +} \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/Export/Materials/UrpLitMaterialExporter.cs.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/Export/Materials/UrpLitMaterialExporter.cs.meta new file mode 100644 index 000000000..37020197d --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/Export/Materials/UrpLitMaterialExporter.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 8832f807c30a420d95aeaee15a1fbff7 +timeCreated: 1722269933 \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/Export/Materials/UrpUniUnlitMaterialExporter.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/Export/Materials/UrpUniUnlitMaterialExporter.cs new file mode 100644 index 000000000..05670b81a --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/Export/Materials/UrpUniUnlitMaterialExporter.cs @@ -0,0 +1,79 @@ +using System; +using UniGLTF.UniUnlit; +using UnityEngine; + +namespace UniGLTF +{ + public class UrpUniUnlitMaterialExporter + { + public Shader Shader { get; set; } + + /// + /// "UniGLTF/UniUnlit" シェーダのマテリアルをエクスポートする。 + /// + /// プロパティに互換性がある他のシェーダを指定することもできる。 + /// + public UrpUniUnlitMaterialExporter(Shader shader = null) + { + Shader = shader != null ? shader : Shader.Find("UniGLTF/UniUnlit"); + } + + public bool TryExportMaterial(Material src, ITextureExporter textureExporter, out glTFMaterial dst) + { + try + { + if (src == null) throw new ArgumentNullException(nameof(src)); + if (textureExporter == null) throw new ArgumentNullException(nameof(textureExporter)); + if (src.shader != Shader || Shader == null) throw new UniGLTFShaderNotMatchedInternalException(src.shader); + + dst = glTF_KHR_materials_unlit.CreateDefault(); + dst.name = src.name; + + var context = new UniUnlitContext(src); + + dst.alphaMode = context.RenderMode switch + { + UniUnlitRenderMode.Opaque => glTFBlendMode.OPAQUE.ToString(), + UniUnlitRenderMode.Cutout => glTFBlendMode.MASK.ToString(), + UniUnlitRenderMode.Transparent => glTFBlendMode.BLEND.ToString(), + _ => throw new ArgumentOutOfRangeException(), + }; + dst.alphaCutoff = context.Cutoff; + dst.doubleSided = context.CullMode != UniUnlitCullMode.Back; + + dst.pbrMetallicRoughness.baseColorFactor = context.MainColorSrgb + .ToFloat4(ColorSpace.sRGB, ColorSpace.Linear); + if (context.MainTexture != null) + { + var needsAlpha = context.RenderMode != UniUnlitRenderMode.Opaque; + var index = textureExporter.RegisterExportingAsSRgb(context.MainTexture, needsAlpha); + if (index >= 0) + { + dst.pbrMetallicRoughness.baseColorTexture = new glTFMaterialBaseColorTextureInfo + { + index = index, + texCoord = 0, + }; + GltfMaterialExportUtils.ExportTextureTransform( + context.MainTextureOffset, + context.MainTextureScale, + dst.pbrMetallicRoughness.baseColorTexture); + } + } + + return true; + } + catch (UniGLTFShaderNotMatchedInternalException) + { + dst = default; + return false; + } + catch (Exception e) + { + Debug.LogException(e); + dst = default; + return false; + } + } + } +} \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/Export/Materials/UrpUniUnlitMaterialExporter.cs.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/Export/Materials/UrpUniUnlitMaterialExporter.cs.meta new file mode 100644 index 000000000..1c986fd4f --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/Export/Materials/UrpUniUnlitMaterialExporter.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 5b17f3928c684fc1a9beda10797b0e76 +timeCreated: 1722613258 \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/Export/Materials/UrpUnlitMaterialExporter.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/Export/Materials/UrpUnlitMaterialExporter.cs new file mode 100644 index 000000000..67659c474 --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/Export/Materials/UrpUnlitMaterialExporter.cs @@ -0,0 +1,50 @@ +using System; +using UnityEngine; + +namespace UniGLTF +{ + public class UrpUnlitMaterialExporter + { + public Shader Shader { get; set; } + + /// + /// "Universal Render Pipeline/Unlit" シェーダのマテリアルをエクスポートする。 + /// + /// プロパティに互換性がある他のシェーダを指定することもできる。 + /// + public UrpUnlitMaterialExporter(Shader shader = null) + { + Shader = shader != null ? shader : Shader.Find("Universal Render Pipeline/Unlit"); + } + + public bool TryExportMaterial(Material src, ITextureExporter textureExporter, out glTFMaterial dst) + { + try + { + if (src == null) throw new ArgumentNullException(nameof(src)); + if (textureExporter == null) throw new ArgumentNullException(nameof(textureExporter)); + if (src.shader != Shader || Shader == null) throw new UniGLTFShaderNotMatchedInternalException(src.shader); + + dst = glTF_KHR_materials_unlit.CreateDefault(); + dst.name = src.name; + + var context = new UrpUnlitContext(src); + UrpLitMaterialExporter.ExportSurfaceSettings(context, dst, textureExporter); + UrpLitMaterialExporter.ExportBaseColor(context, dst, textureExporter); + + return true; + } + catch (UniGLTFShaderNotMatchedInternalException) + { + dst = default; + return false; + } + catch (Exception e) + { + Debug.LogException(e); + dst = default; + return false; + } + } + } +} \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/Export/Materials/UrpUnlitMaterialExporter.cs.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/Export/Materials/UrpUnlitMaterialExporter.cs.meta new file mode 100644 index 000000000..9924e9e80 --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/Export/Materials/UrpUnlitMaterialExporter.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: a90bb1e911744bbab916950324c70e52 +timeCreated: 1722614768 \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/Export/UrpGltfMaterialExporter.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/Export/UrpGltfMaterialExporter.cs new file mode 100644 index 000000000..e1f1d5921 --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/Export/UrpGltfMaterialExporter.cs @@ -0,0 +1,22 @@ +using UnityEngine; + +namespace UniGLTF +{ + public class UrpGltfMaterialExporter : IMaterialExporter + { + public UrpLitMaterialExporter UrpLitExporter { get; set; } = new(); + public UrpUnlitMaterialExporter UrpUnlitExporter { get; set; } = new(); + public UrpUniUnlitMaterialExporter UrpUniUnlitExporter { get; set; } = new(); + public UrpFallbackMaterialExporter FallbackExporter { get; set; } = new(); + + public glTFMaterial ExportMaterial(Material m, ITextureExporter textureExporter, GltfExportSettings settings) + { + if (UrpLitExporter.TryExportMaterial(m, textureExporter, out var dst)) return dst; + if (UrpUnlitExporter.TryExportMaterial(m, textureExporter, out dst)) return dst; + if (UrpUniUnlitExporter.TryExportMaterial(m, textureExporter, out dst)) return dst; + + Debug.Log($"Material `{m.name}` fallbacks."); + return FallbackExporter.ExportMaterial(m, textureExporter); + } + } +} \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/Export/UrpGltfMaterialExporter.cs.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/Export/UrpGltfMaterialExporter.cs.meta new file mode 100644 index 000000000..64d75fa33 --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/Export/UrpGltfMaterialExporter.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 943c27f3f6054f25b4c0bf7e4cd50eff +timeCreated: 1722269861 \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/Import/Materials/UrpGltfDefaultMaterialImporter.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/Import/Materials/UrpGltfDefaultMaterialImporter.cs index b6e3cd90d..260a0c1b0 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/Import/Materials/UrpGltfDefaultMaterialImporter.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/Import/Materials/UrpGltfDefaultMaterialImporter.cs @@ -1,27 +1,65 @@ using System; using System.Collections.Generic; using UnityEngine; +using UnityEngine.Rendering; namespace UniGLTF { /// /// Generate the descriptor of the glTF default material. + /// + /// https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#default-material /// - public static class UrpGltfDefaultMaterialImporter + public class UrpGltfDefaultMaterialImporter { - public static MaterialDescriptor CreateParam() + public Shader Shader { get; set; } + + public UrpGltfDefaultMaterialImporter(Shader shader = null) + { + Shader = shader != null ? shader : Shader.Find("Universal Render Pipeline/Lit"); + } + + public MaterialDescriptor CreateParam(string materialName) { - // FIXME return new MaterialDescriptor( - "__default__", - UrpGltfPbrMaterialImporter.Shader, - default, + string.IsNullOrEmpty(materialName) ? "__default__" : materialName, + Shader, + null, new Dictionary(), new Dictionary(), new Dictionary(), new Dictionary(), - new List>() + new List> { GenerateDefaultMaterial } ); } + + public static void GenerateDefaultMaterial(Material dst) + { + var context = new UrpLitContext(dst); + context.UnsafeEditMode = true; + + context.SurfaceType = UrpLitSurfaceType.Opaque; + context.IsAlphaClipEnabled = false; + context.CullMode = CullMode.Back; + + context.BaseColorSrgb = new Color(1, 1, 1, 1); + context.BaseTexture = null; + + context.WorkflowType = UrpLitWorkflowType.Metallic; + context.SmoothnessTextureChannel = UrpLitSmoothnessMapChannel.SpecularMetallicAlpha; + context.Metallic = 1f; + context.Smoothness = 0f; + context.MetallicGlossMap = null; + + context.OcclusionTexture = null; + + context.BumpMap = null; + + context.IsEmissionEnabled = false; + context.EmissionColorLinear = new Color(0, 0, 0, 0); + context.EmissionTexture = null; + + context.Validate(); + } } } \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/Import/Materials/UrpGltfPbrMaterialImporter.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/Import/Materials/UrpGltfPbrMaterialImporter.cs index dbc25e26d..11586d04d 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/Import/Materials/UrpGltfPbrMaterialImporter.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/Import/Materials/UrpGltfPbrMaterialImporter.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; +using System.Threading.Tasks; using UnityEngine; +using UnityEngine.Rendering; namespace UniGLTF { @@ -9,26 +11,19 @@ namespace UniGLTF /// /// see: https://github.com/Unity-Technologies/Graphics/blob/v7.5.3/com.unity.render-pipelines.universal/Editor/UniversalRenderPipelineMaterialUpgrader.cs#L354-L379 /// - public static class UrpGltfPbrMaterialImporter + public class UrpGltfPbrMaterialImporter { - public const string ShaderName = "Universal Render Pipeline/Lit"; + /// + /// Universal Render Pipeline/Lit とプロパティやキーワードに互換があるカスタムシェーダに置換可能。 + /// + public Shader Shader { get; set; } - private static readonly int SrcBlend = Shader.PropertyToID("_SrcBlend"); - private static readonly int DstBlend = Shader.PropertyToID("_DstBlend"); - private static readonly int ZWrite = Shader.PropertyToID("_ZWrite"); - private static readonly int Cutoff = Shader.PropertyToID("_Cutoff"); - - public static Shader Shader => Shader.Find(ShaderName); - - private enum BlendMode + public UrpGltfPbrMaterialImporter(Shader shader = null) { - Opaque, - Cutout, - Fade, - Transparent + Shader = shader != null ? shader : Shader.Find("Universal Render Pipeline/Lit"); } - public static bool TryCreateParam(GltfData data, int i, out MaterialDescriptor matDesc) + public bool TryCreateParam(GltfData data, int i, out MaterialDescriptor matDesc) { if (i < 0 || i >= data.GLTF.materials.Count) { @@ -36,161 +31,142 @@ namespace UniGLTF return false; } - var textureSlots = new Dictionary(); - var floatValues = new Dictionary(); - var colors = new Dictionary(); - var vectors = new Dictionary(); - var actions = new List>(); var src = data.GLTF.materials[i]; - - TextureDescriptor? standardTexDesc = default; - if (src.pbrMetallicRoughness != null || src.occlusionTexture != null) - { - if (src.pbrMetallicRoughness.metallicRoughnessTexture != null || src.occlusionTexture != null) - { - if (GltfPbrTextureImporter.TryStandardTexture(data, src, out var key, out var desc)) - { - if (string.IsNullOrEmpty(desc.UnityObjectName)) - { - throw new ArgumentNullException(); - } - standardTexDesc = desc; - } - } - - if (src.pbrMetallicRoughness.baseColorFactor != null && src.pbrMetallicRoughness.baseColorFactor.Length == 4) - { - // from _Color ! - colors.Add("_BaseColor", - src.pbrMetallicRoughness.baseColorFactor.ToColor4(ColorSpace.Linear, ColorSpace.sRGB) - ); - } - - if (src.pbrMetallicRoughness.baseColorTexture != null && src.pbrMetallicRoughness.baseColorTexture.index != -1) - { - if (GltfPbrTextureImporter.TryBaseColorTexture(data, src, out var key, out var desc)) - { - // from _MainTex ! - textureSlots.Add("_BaseMap", desc); - } - } - - if (src.pbrMetallicRoughness.metallicRoughnessTexture != null && src.pbrMetallicRoughness.metallicRoughnessTexture.index != -1 && standardTexDesc.HasValue) - { - actions.Add(material => material.EnableKeyword("_METALLICSPECGLOSSMAP")); - textureSlots.Add("_MetallicGlossMap", standardTexDesc.Value); - // Set 1.0f as hard-coded. See: https://github.com/dwango/UniVRM/issues/212. - floatValues.Add("_Metallic", 1.0f); - floatValues.Add("_GlossMapScale", 1.0f); - // default value is 0.5 ! - floatValues.Add("_Smoothness", 1.0f); - } - else - { - floatValues.Add("_Metallic", src.pbrMetallicRoughness.metallicFactor); - // from _Glossiness ! - floatValues.Add("_Smoothness", 1.0f - src.pbrMetallicRoughness.roughnessFactor); - } - } - - if (src.normalTexture != null && src.normalTexture.index != -1) - { - actions.Add(material => material.EnableKeyword("_NORMALMAP")); - if (GltfPbrTextureImporter.TryNormalTexture(data, src, out var key, out var desc)) - { - textureSlots.Add("_BumpMap", desc); - floatValues.Add("_BumpScale", src.normalTexture.scale); - } - } - - if (src.occlusionTexture != null && src.occlusionTexture.index != -1 && standardTexDesc.HasValue) - { - textureSlots.Add("_OcclusionMap", standardTexDesc.Value); - floatValues.Add("_OcclusionStrength", src.occlusionTexture.strength); - } - - if (src.emissiveFactor != null - || (src.emissiveTexture != null && src.emissiveTexture.index != -1)) - { - actions.Add(material => - { - material.EnableKeyword("_EMISSION"); - material.globalIlluminationFlags &= ~MaterialGlobalIlluminationFlags.EmissiveIsBlack; - }); - - var emissiveFactor = GltfMaterialImportUtils.ImportLinearEmissiveFactor(data, src); - if (emissiveFactor.HasValue) - { - colors.Add("_EmissionColor", emissiveFactor.Value); - } - - if (src.emissiveTexture != null && src.emissiveTexture.index != -1) - { - if (GltfPbrTextureImporter.TryEmissiveTexture(data, src, out var key, out var desc)) - { - textureSlots.Add("_EmissionMap", desc); - } - } - } - - actions.Add(material => - { - BlendMode blendMode = BlendMode.Opaque; - // https://forum.unity.com/threads/standard-material-shader-ignoring-setfloat-property-_mode.344557/#post-2229980 - switch (src.alphaMode) - { - case "BLEND": - blendMode = BlendMode.Fade; - material.SetOverrideTag("RenderType", "Transparent"); - material.SetInt(SrcBlend, (int)UnityEngine.Rendering.BlendMode.SrcAlpha); - material.SetInt(DstBlend, (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); - material.SetInt(ZWrite, 0); - material.DisableKeyword("_ALPHATEST_ON"); - material.EnableKeyword("_ALPHABLEND_ON"); - material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); - material.renderQueue = 3000; - break; - - case "MASK": - blendMode = BlendMode.Cutout; - material.SetOverrideTag("RenderType", "TransparentCutout"); - material.SetInt(SrcBlend, (int)UnityEngine.Rendering.BlendMode.One); - material.SetInt(DstBlend, (int)UnityEngine.Rendering.BlendMode.Zero); - material.SetInt(ZWrite, 1); - material.SetFloat(Cutoff, src.alphaCutoff); - material.EnableKeyword("_ALPHATEST_ON"); - material.DisableKeyword("_ALPHABLEND_ON"); - material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); - material.renderQueue = 2450; - - break; - - default: // OPAQUE - blendMode = BlendMode.Opaque; - material.SetOverrideTag("RenderType", ""); - material.SetInt(SrcBlend, (int)UnityEngine.Rendering.BlendMode.One); - material.SetInt(DstBlend, (int)UnityEngine.Rendering.BlendMode.Zero); - material.SetInt(ZWrite, 1); - material.DisableKeyword("_ALPHATEST_ON"); - material.DisableKeyword("_ALPHABLEND_ON"); - material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); - material.renderQueue = -1; - break; - } - - material.SetFloat("_Mode", (float)blendMode); - }); - matDesc = new MaterialDescriptor( GltfMaterialImportUtils.ImportMaterialName(i, src), Shader, null, - textureSlots, - floatValues, - colors, - vectors, - actions); + new Dictionary(), + new Dictionary(), + new Dictionary(), + new Dictionary(), + new List>(), + new [] { (MaterialDescriptor.MaterialGenerateAsyncFunc)AsyncAction } + ); return true; + + Task AsyncAction(Material x, GetTextureAsyncFunc y, IAwaitCaller z) => GenerateMaterialAsync(data, src, x, y, z); + } + + public static async Task GenerateMaterialAsync(GltfData data, glTFMaterial src, Material dst, GetTextureAsyncFunc getTextureAsync, IAwaitCaller awaitCaller) + { + var context = new UrpLitContext(dst); + context.UnsafeEditMode = true; + + ImportSurfaceSettings(src, context); + await ImportBaseColorAsync(data, src, context, getTextureAsync, awaitCaller); + await ImportMetallicSmoothnessAsync(data, src, context, getTextureAsync, awaitCaller); + await ImportOcclusionAsync(data, src, context, getTextureAsync, awaitCaller); + await ImportNormalAsync(data, src, context, getTextureAsync, awaitCaller); + await ImportEmissionAsync(data, src, context, getTextureAsync, awaitCaller); + + context.Validate(); + } + + public static void ImportSurfaceSettings(glTFMaterial src, UrpLitContext context) + { + context.SurfaceType = src.alphaMode switch + { + "OPAQUE" => UrpLitSurfaceType.Opaque, + "MASK" => UrpLitSurfaceType.Transparent, + "BLEND" => UrpLitSurfaceType.Transparent, + _ => UrpLitSurfaceType.Opaque, + }; + context.BlendMode = context.SurfaceType switch + { + UrpLitSurfaceType.Transparent => UrpLitBlendMode.Alpha, + _ => UrpLitBlendMode.Alpha, + }; + context.IsAlphaClipEnabled = src.alphaMode switch + { + "MASK" => true, + _ => false, + }; + context.Cutoff = src.alphaCutoff; + context.CullMode = src.doubleSided ? CullMode.Off : CullMode.Back; + } + + public static async Task ImportBaseColorAsync(GltfData data, glTFMaterial src, UrpLitContext context, GetTextureAsyncFunc getTextureAsync, IAwaitCaller awaitCaller) + { + var baseColorFactor = GltfMaterialImportUtils.ImportLinearBaseColorFactor(data, src); + if (baseColorFactor.HasValue) + { + context.BaseColorSrgb = baseColorFactor.Value.gamma; + } + + if (src is { pbrMetallicRoughness: { baseColorTexture: { index: >= 0 } } }) + { + if (GltfPbrTextureImporter.TryBaseColorTexture(data, src, out _, out var desc)) + { + context.BaseTexture = await getTextureAsync(desc, awaitCaller); + context.BaseTextureOffset = desc.Offset; + context.BaseTextureScale = desc.Scale; + } + } + } + + public static async Task ImportMetallicSmoothnessAsync(GltfData data, glTFMaterial src, UrpLitContext context, GetTextureAsyncFunc getTextureAsync, IAwaitCaller awaitCaller) + { + context.WorkflowType = UrpLitWorkflowType.Metallic; + context.SmoothnessTextureChannel = UrpLitSmoothnessMapChannel.SpecularMetallicAlpha; + context.Metallic = src.pbrMetallicRoughness.metallicFactor; + context.Smoothness = 1.0f - src.pbrMetallicRoughness.roughnessFactor; + + if (src is { pbrMetallicRoughness: { metallicRoughnessTexture: { index: >= 0 } } }) + { + if (GltfPbrTextureImporter.TryStandardTexture(data, src, out _, out var desc)) + { + context.MetallicGlossMap = await getTextureAsync(desc, awaitCaller); + context.Metallic = 1; + context.Smoothness = 1; + } + } + } + + public static async Task ImportOcclusionAsync(GltfData data, glTFMaterial src, UrpLitContext context, GetTextureAsyncFunc getTextureAsync, IAwaitCaller awaitCaller) + { + if (src is { occlusionTexture: { index: >= 0 } }) + { + if (GltfPbrTextureImporter.TryStandardTexture(data, src, out _, out var desc)) + { + context.OcclusionTexture = await getTextureAsync(desc, awaitCaller); + context.OcclusionStrength = src.occlusionTexture.strength; + } + } + } + + private static async Task ImportNormalAsync(GltfData data, glTFMaterial src, UrpLitContext context, GetTextureAsyncFunc getTextureAsync, IAwaitCaller awaitCaller) + { + if (src.normalTexture is { index: >= 0 }) + { + if (GltfPbrTextureImporter.TryNormalTexture(data, src, out _, out var desc)) + { + context.BumpMap = await getTextureAsync(desc, awaitCaller); + context.BumpScale = src.normalTexture.scale; + } + } + } + + private static async Task ImportEmissionAsync(GltfData data, glTFMaterial src, UrpLitContext context, GetTextureAsyncFunc getTextureAsync, IAwaitCaller awaitCaller) + { + var emissiveFactor = GltfMaterialImportUtils.ImportLinearEmissiveFactor(data, src); + if (emissiveFactor.HasValue) + { + context.EmissionColorLinear = emissiveFactor.Value; + } + + if (src is { emissiveTexture: { index: >= 0 } }) + { + if (GltfPbrTextureImporter.TryEmissiveTexture(data, src, out _, out var desc)) + { + context.EmissionTexture = await getTextureAsync(desc, awaitCaller); + } + } + + if (context.EmissionColorLinear is {maxColorComponent: > 0} || context.EmissionTexture != null) + { + context.IsEmissionEnabled = true; + } } } } diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/Import/UrpGltfMaterialDescriptorGenerator.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/Import/UrpGltfMaterialDescriptorGenerator.cs index b1dcdff1e..2b2c4bae8 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/Import/UrpGltfMaterialDescriptorGenerator.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/Import/UrpGltfMaterialDescriptorGenerator.cs @@ -1,6 +1,3 @@ -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; using UnityEngine; namespace UniGLTF @@ -10,30 +7,22 @@ namespace UniGLTF /// public sealed class UrpGltfMaterialDescriptorGenerator : IMaterialDescriptorGenerator { + public UrpGltfPbrMaterialImporter PbrMaterialImporter { get; } = new(); + public UrpGltfDefaultMaterialImporter DefaultMaterialImporter { get; } = new(); + public MaterialDescriptor Get(GltfData data, int i) { if (BuiltInGltfUnlitMaterialImporter.TryCreateParam(data, i, out var param)) return param; - if (UrpGltfPbrMaterialImporter.TryCreateParam(data, i, out param)) return param; - // fallback + if (PbrMaterialImporter.TryCreateParam(data, i, out param)) return param; + + // NOTE: Fallback to default material if (Symbols.VRM_DEVELOP) { Debug.LogWarning($"material: {i} out of range. fallback"); } - - return new MaterialDescriptor( - GltfMaterialImportUtils.ImportMaterialName(i, null), - UrpGltfPbrMaterialImporter.Shader, - null, - new Dictionary(), - new Dictionary(), - new Dictionary(), - new Dictionary(), - new Collection>()); + return GetGltfDefault(GltfMaterialImportUtils.ImportMaterialName(i, null)); } - public MaterialDescriptor GetGltfDefault() - { - return UrpGltfDefaultMaterialImporter.CreateParam(); - } + public MaterialDescriptor GetGltfDefault(string materialName = null) => DefaultMaterialImporter.CreateParam(materialName); } } \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil.meta new file mode 100644 index 000000000..349fc6a09 --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 4a35a0639a7f4eb4b2c5fb8225803ce3 +timeCreated: 1722270899 \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit.meta new file mode 100644 index 000000000..fb73c7173 --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 2100c40775e3446bb05f63f32820930a +timeCreated: 1722270911 \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit/UrpBaseShaderContext.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit/UrpBaseShaderContext.cs new file mode 100644 index 000000000..241203156 --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit/UrpBaseShaderContext.cs @@ -0,0 +1,163 @@ +using UnityEngine; +using UnityEngine.Rendering; + +namespace UniGLTF +{ + public abstract class UrpBaseShaderContext + { + private static readonly int Surface = Shader.PropertyToID("_Surface"); + private static readonly int AlphaClip = Shader.PropertyToID("_AlphaClip"); + private static readonly int Blend = Shader.PropertyToID("_Blend"); + private static readonly int Cull = Shader.PropertyToID("_Cull"); + private static readonly int BaseColorProp = Shader.PropertyToID("_BaseColor"); + private static readonly int BaseMap = Shader.PropertyToID("_BaseMap"); + private static readonly int CutoffProp = Shader.PropertyToID("_Cutoff"); + private static readonly int ZWrite = Shader.PropertyToID("_ZWrite"); + private static readonly int SrcBlend = Shader.PropertyToID("_SrcBlend"); + private static readonly int DstBlend = Shader.PropertyToID("_DstBlend"); + private static readonly string SurfaceTypeTransparentKeyword = "_SURFACE_TYPE_TRANSPARENT"; + private static readonly string AlphaTestOnKeyword = "_ALPHATEST_ON"; + private static readonly string AlphaPremultiplyOnKeyword = "_ALPHAPREMULTIPLY_ON"; + private static readonly string AlphaModulateOnKeyword = "_ALPHAMODULATE_ON"; + + protected UrpBaseShaderContext(Material material) + { + Material = material; + } + + public Material Material { get; } + + /// + /// これが有効な場合、Validate() 関数が呼ばれるべき場合でも自動的に呼ばれなくなります。 + /// + /// 処理最適化目的で使用できます。 + /// + public bool UnsafeEditMode { get; set; } = false; + + public UrpLitSurfaceType SurfaceType + { + get => (UrpLitSurfaceType)Material.GetFloat(Surface); + set + { + Material.SetFloat(Surface, (float)value); + if (!UnsafeEditMode) Validate(); + } + } + + public UrpLitBlendMode BlendMode + { + get => (UrpLitBlendMode)Material.GetFloat(Blend); + set + { + Material.SetFloat(Blend, (float)value); + if (!UnsafeEditMode) Validate(); + } + } + + public bool IsAlphaClipEnabled + { + get => Material.GetFloat(AlphaClip) >= 0.5f; + set + { + Material.SetFloat(AlphaClip, value ? 1.0f : 0.0f); + if (!UnsafeEditMode) Validate(); + } + } + + public CullMode CullMode + { + get => (CullMode)Material.GetFloat(Cull); + set + { + Material.SetFloat(Cull, (float)value); + Material.doubleSidedGI = value != CullMode.Back; + } + } + + public Color BaseColorSrgb + { + get => Material.GetColor(BaseColorProp); + set => Material.SetColor(BaseColorProp, value); + } + + public Texture BaseTexture + { + get => Material.GetTexture(BaseMap); + set => Material.SetTexture(BaseMap, value); + } + + public Vector2 BaseTextureOffset + { + get => Material.GetTextureOffset(BaseMap); + set => Material.SetTextureOffset(BaseMap, value); + } + + public Vector2 BaseTextureScale + { + get => Material.GetTextureScale(BaseMap); + set => Material.SetTextureScale(BaseMap, value); + } + + public float Cutoff + { + get => Material.GetFloat(CutoffProp); + set => Material.SetFloat(CutoffProp, value); + } + + + public virtual void Validate() + { + // Surface Type + var surfaceType = (UrpLitSurfaceType)Material.GetFloat(Surface); + Material.SetKeyword(SurfaceTypeTransparentKeyword, surfaceType != UrpLitSurfaceType.Opaque); + + // Alpha Clip + var alphaClip = Material.GetFloat(AlphaClip) >= 0.5f; + Material.SetKeyword(AlphaTestOnKeyword, alphaClip); + + // Blend Mode + var blendMode = (UrpLitBlendMode)Material.GetFloat(Blend); + Material.SetKeyword(AlphaPremultiplyOnKeyword, blendMode == UrpLitBlendMode.Premultiply); + Material.SetKeyword(AlphaModulateOnKeyword, blendMode == UrpLitBlendMode.Additive); + + // ZWrite + var zWrite = surfaceType == UrpLitSurfaceType.Opaque; + Material.SetFloat(ZWrite, zWrite ? 1.0f : 0.0f); + Material.SetShaderPassEnabled("DepthOnly", zWrite); + + // Render Settings + Material.SetFloat(SrcBlend, (surfaceType, blendMode) switch + { + (UrpLitSurfaceType.Opaque, _) => (float)UnityEngine.Rendering.BlendMode.One, + (UrpLitSurfaceType.Transparent, UrpLitBlendMode.Alpha) => (float)UnityEngine.Rendering.BlendMode.SrcAlpha, + (UrpLitSurfaceType.Transparent, UrpLitBlendMode.Premultiply) => (float)UnityEngine.Rendering.BlendMode.One, + (UrpLitSurfaceType.Transparent, UrpLitBlendMode.Additive) => (float)UnityEngine.Rendering.BlendMode.One, + (UrpLitSurfaceType.Transparent, UrpLitBlendMode.Multiply) => (float)UnityEngine.Rendering.BlendMode.DstColor, + _ => (float)UnityEngine.Rendering.BlendMode.One, + }); + Material.SetFloat(DstBlend, (surfaceType, blendMode) switch + { + (UrpLitSurfaceType.Opaque, _) => (float)UnityEngine.Rendering.BlendMode.Zero, + (UrpLitSurfaceType.Transparent, UrpLitBlendMode.Alpha) => (float)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha, + (UrpLitSurfaceType.Transparent, UrpLitBlendMode.Premultiply) => (float)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha, + (UrpLitSurfaceType.Transparent, UrpLitBlendMode.Additive) => (float)UnityEngine.Rendering.BlendMode.One, + (UrpLitSurfaceType.Transparent, UrpLitBlendMode.Multiply) => (float)UnityEngine.Rendering.BlendMode.Zero, + _ => (float) UnityEngine.Rendering.BlendMode.Zero, + }); + Material.SetOverrideTag("RenderType", (surfaceType, alphaClip) switch + { + (UrpLitSurfaceType.Opaque, false) => "Opaque", + (UrpLitSurfaceType.Opaque, true) => "TransparentCutout", + (UrpLitSurfaceType.Transparent, _) => "Transparent", + _ => "Opaque", + }); + Material.renderQueue = (surfaceType, alphaClip) switch + { + (UrpLitSurfaceType.Opaque, false) => (int)RenderQueue.Geometry, + (UrpLitSurfaceType.Opaque, true) => (int)RenderQueue.AlphaTest, + (UrpLitSurfaceType.Transparent, _) => (int)RenderQueue.Transparent, + _ => Material.shader.renderQueue, + }; + } + } +} \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit/UrpBaseShaderContext.cs.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit/UrpBaseShaderContext.cs.meta new file mode 100644 index 000000000..2d2ffbfbd --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit/UrpBaseShaderContext.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: a0a218f533e64925a87626ce8129f264 +timeCreated: 1722615731 \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit/UrpLitBlendMode.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit/UrpLitBlendMode.cs new file mode 100644 index 000000000..2d09f28a5 --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit/UrpLitBlendMode.cs @@ -0,0 +1,10 @@ +namespace UniGLTF +{ + public enum UrpLitBlendMode + { + Alpha = 0, + Premultiply = 1, + Additive = 2, + Multiply = 3, + } +} \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit/UrpLitBlendMode.cs.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit/UrpLitBlendMode.cs.meta new file mode 100644 index 000000000..81c0e8029 --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit/UrpLitBlendMode.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 307c409e09f74fed8caaaedfdf794ef9 +timeCreated: 1722351228 \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit/UrpLitContext.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit/UrpLitContext.cs new file mode 100644 index 000000000..920454f63 --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit/UrpLitContext.cs @@ -0,0 +1,204 @@ +using System; +using UnityEngine; +using UnityEngine.Rendering; + +namespace UniGLTF +{ + /// + /// "Universal Render Pipeline/Lit" シェーダーのプロパティを操作するためのクラス + /// + /// glTF との読み書きに必要な機能だけ実装する + /// + /// 非対応項目 + /// - Detail Texture + /// - Specular Highlights Toggle + /// - Environment Reflections Toggle + /// - Sorting Priority + /// + public class UrpLitContext : UrpBaseShaderContext + { + private static readonly int WorkflowMode = Shader.PropertyToID("_WorkflowMode"); + private static readonly int EmissionColor = Shader.PropertyToID("_EmissionColor"); + private static readonly int EmissionMap = Shader.PropertyToID("_EmissionMap"); + private static readonly int OcclusionMap = Shader.PropertyToID("_OcclusionMap"); + private static readonly int ParallaxMap = Shader.PropertyToID("_ParallaxMap"); + private static readonly int SmoothnessProp = Shader.PropertyToID("_Smoothness"); + private static readonly int SmoothnessTextureChannelProp = Shader.PropertyToID("_SmoothnessTextureChannel"); + private static readonly int MetallicProp = Shader.PropertyToID("_Metallic"); + private static readonly int MetallicGlossMapProp = Shader.PropertyToID("_MetallicGlossMap"); + private static readonly int SpecColorProp = Shader.PropertyToID("_SpecColor"); + private static readonly int SpecGlossMapProp = Shader.PropertyToID("_SpecGlossMap"); + private static readonly int BumpScaleProp = Shader.PropertyToID("_BumpScale"); + private static readonly int BumpMapProp = Shader.PropertyToID("_BumpMap"); + + private static readonly string SpecularSetupKeyword = "_SPECULAR_SETUP"; + private static readonly string MetallicSpecGlossMapKeyword = "_METALLICSPECGLOSSMAP"; + private static readonly string SmoothnessTextureAlbedoChannelAKeyword = "_SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A"; + private static readonly string NormalMapKeyword = "_NORMALMAP"; + private static readonly string EmissionKeyword = "_EMISSION"; + private static readonly string OcclusionMapKeyword = "_OCCLUSIONMAP"; + private static readonly string ParallaxMapKeyword = "_PARALLAXMAP"; + private static readonly int OcclusionStrengthProp = Shader.PropertyToID("_OcclusionStrength"); + private static readonly int ParallaxProp = Shader.PropertyToID("_Parallax"); + + public UrpLitContext(Material material) : base(material) + { + + } + + public UrpLitWorkflowType WorkflowType + { + get => (UrpLitWorkflowType)Material.GetFloat(WorkflowMode); + set + { + Material.SetFloat(WorkflowMode, (float)value); + if (!UnsafeEditMode) Validate(); + } + } + + public float Smoothness + { + get => Material.GetFloat(SmoothnessProp); + set => Material.SetFloat(SmoothnessProp, value); + } + + public UrpLitSmoothnessMapChannel SmoothnessTextureChannel + { + // NOTE: Float Prop 以外に条件があるので、Keyword から読み取った方が確実 + get => Material.IsKeywordEnabled(SmoothnessTextureAlbedoChannelAKeyword) ? UrpLitSmoothnessMapChannel.AlbedoAlpha : UrpLitSmoothnessMapChannel.SpecularMetallicAlpha; + set + { + Material.SetFloat(SmoothnessTextureChannelProp, (float)value); + if (!UnsafeEditMode) Validate(); + } + } + + public float Metallic + { + // NOTE: Metallic ワークフロー専用 + get => Material.GetFloat(MetallicProp); + set => Material.SetFloat(MetallicProp, value); + } + + public Texture MetallicGlossMap + { + // NOTE: Metallic ワークフロー専用 + get => Material.GetTexture(MetallicGlossMapProp); + set => Material.SetTexture(MetallicGlossMapProp, value); + } + + public Color SpecColorSrgb + { + // NOTE: Specular ワークフロー専用 + get => Material.GetColor(SpecColorProp); + set => Material.SetColor(SpecColorProp, value); + } + + public Texture SpecGlossMap + { + // NOTE: Specular ワークフロー専用 + get => Material.GetTexture(SpecGlossMapProp); + set => Material.SetTexture(SpecGlossMapProp, value); + } + + public float BumpScale + { + get => Material.GetFloat(BumpScaleProp); + set => Material.SetFloat(BumpScaleProp, value); + } + + public Texture BumpMap + { + get => Material.GetTexture(BumpMapProp); + set + { + Material.SetTexture(BumpMapProp, value); + Material.SetKeyword(NormalMapKeyword, value != null); + } + } + + public bool IsEmissionEnabled + { + get => Material.IsKeywordEnabled(EmissionKeyword); + set + { + Material.SetKeyword(EmissionKeyword, value); + if (value) + { + Material.globalIlluminationFlags &= ~MaterialGlobalIlluminationFlags.EmissiveIsBlack; + } + else + { + Material.globalIlluminationFlags |= MaterialGlobalIlluminationFlags.EmissiveIsBlack; + } + } + } + + public Color EmissionColorLinear + { + get => Material.GetColor(EmissionColor); + set => Material.SetColor(EmissionColor, value); + } + + public Texture EmissionTexture + { + get => Material.GetTexture(EmissionMap); + set => Material.SetTexture(EmissionMap, value); + } + + public float OcclusionStrength + { + get => Material.GetFloat(OcclusionStrengthProp); + set => Material.SetFloat(OcclusionStrengthProp, value); + } + + public Texture OcclusionTexture + { + get => Material.GetTexture(OcclusionMap); + set + { + Material.SetTexture(OcclusionMap, value); + Material.SetKeyword(OcclusionMapKeyword, value != null); + } + } + + public float Parallax + { + get => Material.GetFloat(ParallaxProp); + set => Material.SetFloat(ParallaxProp, value); + } + + public Texture ParallaxTexture + { + get => Material.GetTexture(ParallaxMap); + set + { + Material.SetTexture(ParallaxMap, value); + Material.SetKeyword(ParallaxMapKeyword, value != null); + } + } + + /// + /// 複数のプロパティに関連して設定されるキーワードやプロパティなどを更新する + /// + public override void Validate() + { + base.Validate(); + + // Workflow + var workflowType = (UrpLitWorkflowType)Material.GetFloat(WorkflowMode); + var isSpecularSetup = workflowType == UrpLitWorkflowType.Specular; + Material.SetKeyword(SpecularSetupKeyword, isSpecularSetup); + + // GlossMap + var glossMapName = isSpecularSetup ? SpecGlossMapProp : MetallicGlossMapProp; + var hasGlossMap = Material.GetTexture(glossMapName) != null; + Material.SetKeyword(MetallicSpecGlossMapKeyword, hasGlossMap); + + // SmoothnessTextureChannel + var isOpaque = SurfaceType == UrpLitSurfaceType.Opaque; + var smoothnessMapChannel = (UrpLitSmoothnessMapChannel)Material.GetFloat(SmoothnessTextureChannelProp); + Material.SetKeyword(SmoothnessTextureAlbedoChannelAKeyword, isOpaque && smoothnessMapChannel == UrpLitSmoothnessMapChannel.AlbedoAlpha); + } + } +} \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit/UrpLitContext.cs.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit/UrpLitContext.cs.meta new file mode 100644 index 000000000..ace7df81f --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit/UrpLitContext.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: c15ac3fb36ff4e7d8ec271e2cf1fb263 +timeCreated: 1722270619 \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit/UrpLitSmoothnessMapChannel.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit/UrpLitSmoothnessMapChannel.cs new file mode 100644 index 000000000..593f9f728 --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit/UrpLitSmoothnessMapChannel.cs @@ -0,0 +1,8 @@ +namespace UniGLTF +{ + public enum UrpLitSmoothnessMapChannel + { + SpecularMetallicAlpha = 0, + AlbedoAlpha = 1, + } +} \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit/UrpLitSmoothnessMapChannel.cs.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit/UrpLitSmoothnessMapChannel.cs.meta new file mode 100644 index 000000000..159bf2df7 --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit/UrpLitSmoothnessMapChannel.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 5669057b7c2d45de9167a335f222c61d +timeCreated: 1722344104 \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit/UrpLitSurfaceType.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit/UrpLitSurfaceType.cs new file mode 100644 index 000000000..ee85f82c4 --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit/UrpLitSurfaceType.cs @@ -0,0 +1,8 @@ +namespace UniGLTF +{ + public enum UrpLitSurfaceType + { + Opaque = 0, + Transparent = 1, + } +} \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit/UrpLitSurfaceType.cs.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit/UrpLitSurfaceType.cs.meta new file mode 100644 index 000000000..e366b94aa --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit/UrpLitSurfaceType.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 404bf44062364d41a91735181e6ead33 +timeCreated: 1722270974 \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit/UrpLitWorkflowType.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit/UrpLitWorkflowType.cs new file mode 100644 index 000000000..379d787b0 --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit/UrpLitWorkflowType.cs @@ -0,0 +1,8 @@ +namespace UniGLTF +{ + public enum UrpLitWorkflowType + { + Specular = 0, + Metallic = 1, + } +} \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit/UrpLitWorkflowType.cs.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit/UrpLitWorkflowType.cs.meta new file mode 100644 index 000000000..065dd00c4 --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit/UrpLitWorkflowType.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: a76aba2bef494654948abea5eef21fac +timeCreated: 1722271263 \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit/UrpUnlitContext.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit/UrpUnlitContext.cs new file mode 100644 index 000000000..1d4a6c864 --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit/UrpUnlitContext.cs @@ -0,0 +1,12 @@ +using UnityEngine; + +namespace UniGLTF +{ + public class UrpUnlitContext : UrpBaseShaderContext + { + public UrpUnlitContext(Material material) : base(material) + { + + } + } +} \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit/UrpUnlitContext.cs.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit/UrpUnlitContext.cs.meta new file mode 100644 index 000000000..7fc4a5dde --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit/UrpUnlitContext.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 3fe15309261045ba937d6a8dafb6a93d +timeCreated: 1722616677 \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/Utils.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/Utils.meta new file mode 100644 index 000000000..64945a10f --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/Utils.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: f0ed4e9ca99a4447896accb69a065c2e +timeCreated: 1722343812 \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/Utils/InternalMaterialUtils.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/Utils/InternalMaterialUtils.cs new file mode 100644 index 000000000..b6d3136b7 --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/Utils/InternalMaterialUtils.cs @@ -0,0 +1,19 @@ +using UnityEngine; + +namespace UniGLTF +{ + internal static class InternalMaterialUtils + { + public static void SetKeyword(this Material material, string keyword, bool enabled) + { + if (enabled) + { + material.EnableKeyword(keyword); + } + else + { + material.DisableKeyword(keyword); + } + } + } +} \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/Utils/InternalMaterialUtils.cs.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/Utils/InternalMaterialUtils.cs.meta new file mode 100644 index 000000000..b004c841d --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/Utils/InternalMaterialUtils.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: cc1b44f784074898b268882d75b86e23 +timeCreated: 1722343798 \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/Utils/UniGLTFShaderNotMatchedInternalException.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/Utils/UniGLTFShaderNotMatchedInternalException.cs new file mode 100644 index 000000000..d83951461 --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/Utils/UniGLTFShaderNotMatchedInternalException.cs @@ -0,0 +1,9 @@ +using UnityEngine; + +namespace UniGLTF +{ + internal class UniGLTFShaderNotMatchedInternalException : UniGLTFException + { + public UniGLTFShaderNotMatchedInternalException(Shader shader) : base(shader != null ? shader.name : "") { } + } +} \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/Utils/UniGLTFShaderNotMatchedInternalException.cs.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/Utils/UniGLTFShaderNotMatchedInternalException.cs.meta new file mode 100644 index 000000000..af5b0c5b5 --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/Utils/UniGLTFShaderNotMatchedInternalException.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 7857ff1b8d15440f9886f293a747ebb1 +timeCreated: 1722617046 \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/PackageVersion.cs b/Assets/UniGLTF/Runtime/UniGLTF/PackageVersion.cs index 3c4d84a63..ca987f215 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/PackageVersion.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/PackageVersion.cs @@ -4,8 +4,8 @@ namespace UniGLTF public static partial class PackageVersion { public const int MAJOR = 0; - public const int MINOR = 124; - public const int PATCH = 2; - public const string VERSION = "0.124.2"; + public const int MINOR = 125; + public const int PATCH = 0; + public const string VERSION = "0.125.0"; } } diff --git a/Assets/UniGLTF/Runtime/UniGLTF/UniGLTFVersion.cs b/Assets/UniGLTF/Runtime/UniGLTF/UniGLTFVersion.cs index e329b4d15..8e1140f1f 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/UniGLTFVersion.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/UniGLTFVersion.cs @@ -4,8 +4,8 @@ namespace UniGLTF public static partial class UniGLTFVersion { public const int MAJOR = 2; - public const int MINOR = 60; - public const int PATCH = 2; - public const string VERSION = "2.60.2"; + public const int MINOR = 61; + public const int PATCH = 0; + public const string VERSION = "2.61.0"; } } diff --git a/Assets/UniGLTF/Runtime/Utils/UniGLTFLogger.cs b/Assets/UniGLTF/Runtime/Utils/UniGLTFLogger.cs index 594636d4a..07b1e3e25 100644 --- a/Assets/UniGLTF/Runtime/Utils/UniGLTFLogger.cs +++ b/Assets/UniGLTF/Runtime/Utils/UniGLTFLogger.cs @@ -52,7 +52,9 @@ namespace UniGLTF } [System.Diagnostics.Conditional("VRM_DEVELOP")] +#if UNITY_2022_OR_NEWER [HideInCallstack] +#endif public static void Log(string msg, UnityEngine.Object context = null) => s_logger.LogFormat(LogType.Log, context, msg); } } \ No newline at end of file diff --git a/Assets/UniGLTF/Samples~/GltfViewer/GltfViewer.cs b/Assets/UniGLTF/Samples~/GltfViewer/GltfViewer.cs index fcdc21b31..dc8596b53 100644 --- a/Assets/UniGLTF/Samples~/GltfViewer/GltfViewer.cs +++ b/Assets/UniGLTF/Samples~/GltfViewer/GltfViewer.cs @@ -31,7 +31,7 @@ namespace UniGLTF.GltfViewer LoadPathAsync(path); } - async void LoadPathAsync(VRMShaders.PathObject path) + async void LoadPathAsync(PathObject path) { if (_instance) { diff --git a/Assets/UniGLTF/Samples~/GltfViewer/OpenFileDialog/OpenFileDialog.cs b/Assets/UniGLTF/Samples~/GltfViewer/OpenFileDialog/OpenFileDialog.cs index 2da319a5b..47695f73c 100644 --- a/Assets/UniGLTF/Samples~/GltfViewer/OpenFileDialog/OpenFileDialog.cs +++ b/Assets/UniGLTF/Samples~/GltfViewer/OpenFileDialog/OpenFileDialog.cs @@ -2,10 +2,10 @@ namespace UniGLTF.GltfViewer { public static class OpenFileDialog { - public static VRMShaders.PathObject Show(string title, params string[] extensions) + public static PathObject Show(string title, params string[] extensions) { #if UNITY_STANDALONE_WIN - return VRMShaders.PathObject.FromFullPath(FileDialogForWindows.FileDialog(title, extensions)); + return PathObject.FromFullPath(FileDialogForWindows.FileDialog(title, extensions)); #else UnityEngine.Debug.LogWarning("Non-Windows runtime file dialogs are not yet implemented."); return default; diff --git a/Assets/UniGLTF/Samples~/UniHumanoid/HumanBuilderTest.cs b/Assets/UniGLTF/Samples~/UniHumanoid/HumanBuilderTest.cs index b517b14dc..188eb73f3 100644 --- a/Assets/UniGLTF/Samples~/UniHumanoid/HumanBuilderTest.cs +++ b/Assets/UniGLTF/Samples~/UniHumanoid/HumanBuilderTest.cs @@ -119,7 +119,11 @@ namespace UniHumanoid builder.AddLeg(0.1f, 0.3f, 0.4f, 0.1f, 0.1f); var description = AvatarDescription.Create(builder.Skeleton); - var animator = GetComponentOrThrow(); + var animator = GetComponent(); + if (animator == null) + { + throw new System.ArgumentException("no animator"); + } animator.avatar = description.CreateAvatar(root); // create SkinnedMesh for bone visualize @@ -132,7 +136,8 @@ namespace UniHumanoid renderer.sharedMaterial = m_material; //root.gameObject.AddComponent(); - if (TryGetComponent(out var transfer)) + var transfer = GetComponent(); + if (transfer != null) { transfer.Avatar = animator.avatar; transfer.Setup(); diff --git a/Assets/UniGLTF/Tests/Objects.meta b/Assets/UniGLTF/Tests/Objects.meta new file mode 100644 index 000000000..895ef31b1 --- /dev/null +++ b/Assets/UniGLTF/Tests/Objects.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 257f9efac603801459934018928760de +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/UniGLTF/Tests/UniGLTF/4x4_gray_import_as_linear.png b/Assets/UniGLTF/Tests/Objects/4x4_gray_import_as_linear.png similarity index 100% rename from Assets/UniGLTF/Tests/UniGLTF/4x4_gray_import_as_linear.png rename to Assets/UniGLTF/Tests/Objects/4x4_gray_import_as_linear.png diff --git a/Assets/UniGLTF/Tests/UniGLTF/4x4_gray_import_as_linear.png.meta b/Assets/UniGLTF/Tests/Objects/4x4_gray_import_as_linear.png.meta similarity index 86% rename from Assets/UniGLTF/Tests/UniGLTF/4x4_gray_import_as_linear.png.meta rename to Assets/UniGLTF/Tests/Objects/4x4_gray_import_as_linear.png.meta index 34e2b319c..8cff80177 100644 --- a/Assets/UniGLTF/Tests/UniGLTF/4x4_gray_import_as_linear.png.meta +++ b/Assets/UniGLTF/Tests/Objects/4x4_gray_import_as_linear.png.meta @@ -3,7 +3,7 @@ guid: fc1ba24d4a4141d4d9e9ae0a0d3ecd0a TextureImporter: internalIDToNameTable: [] externalObjects: {} - serializedVersion: 11 + serializedVersion: 12 mipmaps: mipMapMode: 0 enableMipMap: 0 @@ -24,6 +24,7 @@ TextureImporter: streamingMipmaps: 0 streamingMipmapsPriority: 0 vTOnly: 0 + ignoreMasterTextureLimit: 0 grayScaleToAlpha: 0 generateCubemap: 6 cubemapConvolution: 0 @@ -62,6 +63,7 @@ TextureImporter: textureFormatSet: 0 ignorePngGamma: 0 applyGammaDecoding: 0 + cookieLightType: 1 platformSettings: - serializedVersion: 3 buildTarget: DefaultTexturePlatform @@ -99,6 +101,18 @@ TextureImporter: overridden: 0 androidETC2FallbackOverride: 0 forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Server + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 spriteSheet: serializedVersion: 2 sprites: [] @@ -112,6 +126,7 @@ TextureImporter: edges: [] weights: [] secondaryTextures: [] + nameFileIdTable: {} spritePackingTag: pSDRemoveMatte: 0 pSDShowRemoveMatteOption: 0 diff --git a/Assets/UniGLTF/Tests/UniGLTF/4x4_gray_import_as_normal_map.png b/Assets/UniGLTF/Tests/Objects/4x4_gray_import_as_normal_map.png similarity index 100% rename from Assets/UniGLTF/Tests/UniGLTF/4x4_gray_import_as_normal_map.png rename to Assets/UniGLTF/Tests/Objects/4x4_gray_import_as_normal_map.png diff --git a/Assets/UniGLTF/Tests/UniGLTF/4x4_gray_import_as_normal_map.png.meta b/Assets/UniGLTF/Tests/Objects/4x4_gray_import_as_normal_map.png.meta similarity index 86% rename from Assets/UniGLTF/Tests/UniGLTF/4x4_gray_import_as_normal_map.png.meta rename to Assets/UniGLTF/Tests/Objects/4x4_gray_import_as_normal_map.png.meta index 4862a8127..aa67d0199 100644 --- a/Assets/UniGLTF/Tests/UniGLTF/4x4_gray_import_as_normal_map.png.meta +++ b/Assets/UniGLTF/Tests/Objects/4x4_gray_import_as_normal_map.png.meta @@ -3,7 +3,7 @@ guid: b5d17df8d14f2324692a7c69f24cf658 TextureImporter: internalIDToNameTable: [] externalObjects: {} - serializedVersion: 11 + serializedVersion: 12 mipmaps: mipMapMode: 0 enableMipMap: 1 @@ -24,6 +24,7 @@ TextureImporter: streamingMipmaps: 0 streamingMipmapsPriority: 0 vTOnly: 0 + ignoreMasterTextureLimit: 0 grayScaleToAlpha: 0 generateCubemap: 6 cubemapConvolution: 0 @@ -62,6 +63,7 @@ TextureImporter: textureFormatSet: 0 ignorePngGamma: 0 applyGammaDecoding: 0 + cookieLightType: 1 platformSettings: - serializedVersion: 3 buildTarget: DefaultTexturePlatform @@ -99,6 +101,18 @@ TextureImporter: overridden: 0 androidETC2FallbackOverride: 0 forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Server + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 spriteSheet: serializedVersion: 2 sprites: [] @@ -112,6 +126,7 @@ TextureImporter: edges: [] weights: [] secondaryTextures: [] + nameFileIdTable: {} spritePackingTag: pSDRemoveMatte: 0 pSDShowRemoveMatteOption: 0 diff --git a/Assets/UniGLTF/Tests/UniGLTF/4x4_gray_import_as_srgb.png b/Assets/UniGLTF/Tests/Objects/4x4_gray_import_as_srgb.png similarity index 100% rename from Assets/UniGLTF/Tests/UniGLTF/4x4_gray_import_as_srgb.png rename to Assets/UniGLTF/Tests/Objects/4x4_gray_import_as_srgb.png diff --git a/Assets/UniGLTF/Tests/UniGLTF/4x4_gray_import_as_srgb.png.meta b/Assets/UniGLTF/Tests/Objects/4x4_gray_import_as_srgb.png.meta similarity index 86% rename from Assets/UniGLTF/Tests/UniGLTF/4x4_gray_import_as_srgb.png.meta rename to Assets/UniGLTF/Tests/Objects/4x4_gray_import_as_srgb.png.meta index 39acaa02f..c2e9bfc6f 100644 --- a/Assets/UniGLTF/Tests/UniGLTF/4x4_gray_import_as_srgb.png.meta +++ b/Assets/UniGLTF/Tests/Objects/4x4_gray_import_as_srgb.png.meta @@ -3,7 +3,7 @@ guid: 0f7acf68f1798ae48a5505519abac457 TextureImporter: internalIDToNameTable: [] externalObjects: {} - serializedVersion: 11 + serializedVersion: 12 mipmaps: mipMapMode: 0 enableMipMap: 0 @@ -24,6 +24,7 @@ TextureImporter: streamingMipmaps: 0 streamingMipmapsPriority: 0 vTOnly: 0 + ignoreMasterTextureLimit: 0 grayScaleToAlpha: 0 generateCubemap: 6 cubemapConvolution: 0 @@ -62,6 +63,7 @@ TextureImporter: textureFormatSet: 0 ignorePngGamma: 0 applyGammaDecoding: 0 + cookieLightType: 1 platformSettings: - serializedVersion: 3 buildTarget: DefaultTexturePlatform @@ -99,6 +101,18 @@ TextureImporter: overridden: 0 androidETC2FallbackOverride: 0 forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Server + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 spriteSheet: serializedVersion: 2 sprites: [] @@ -112,6 +126,7 @@ TextureImporter: edges: [] weights: [] secondaryTextures: [] + nameFileIdTable: {} spritePackingTag: pSDRemoveMatte: 0 pSDShowRemoveMatteOption: 0 diff --git a/Assets/UniGLTF/Tests/UniGLTF/4x4_non_readable.png b/Assets/UniGLTF/Tests/Objects/4x4_non_readable.png similarity index 100% rename from Assets/UniGLTF/Tests/UniGLTF/4x4_non_readable.png rename to Assets/UniGLTF/Tests/Objects/4x4_non_readable.png diff --git a/Assets/UniGLTF/Tests/UniGLTF/4x4_non_readable.png.meta b/Assets/UniGLTF/Tests/Objects/4x4_non_readable.png.meta similarity index 100% rename from Assets/UniGLTF/Tests/UniGLTF/4x4_non_readable.png.meta rename to Assets/UniGLTF/Tests/Objects/4x4_non_readable.png.meta diff --git a/Assets/UniGLTF/Tests/UniGLTF/4x4_non_readable_compressed.DDS b/Assets/UniGLTF/Tests/Objects/4x4_non_readable_compressed.DDS similarity index 100% rename from Assets/UniGLTF/Tests/UniGLTF/4x4_non_readable_compressed.DDS rename to Assets/UniGLTF/Tests/Objects/4x4_non_readable_compressed.DDS diff --git a/Assets/UniGLTF/Tests/UniGLTF/4x4_non_readable_compressed.DDS.meta b/Assets/UniGLTF/Tests/Objects/4x4_non_readable_compressed.DDS.meta similarity index 100% rename from Assets/UniGLTF/Tests/UniGLTF/4x4_non_readable_compressed.DDS.meta rename to Assets/UniGLTF/Tests/Objects/4x4_non_readable_compressed.DDS.meta diff --git a/Assets/UniGLTF/Tests/UniGLTF/New Material.mat b/Assets/UniGLTF/Tests/Objects/New Material.mat similarity index 100% rename from Assets/UniGLTF/Tests/UniGLTF/New Material.mat rename to Assets/UniGLTF/Tests/Objects/New Material.mat diff --git a/Assets/UniGLTF/Tests/UniGLTF/New Material.mat.meta b/Assets/UniGLTF/Tests/Objects/New Material.mat.meta similarity index 100% rename from Assets/UniGLTF/Tests/UniGLTF/New Material.mat.meta rename to Assets/UniGLTF/Tests/Objects/New Material.mat.meta diff --git a/Assets/UniGLTF/Tests/UniGLTF/AssetTests.cs b/Assets/UniGLTF/Tests/UniGLTF/AssetTests.cs index 50b0a6867..1fddabbee 100644 --- a/Assets/UniGLTF/Tests/UniGLTF/AssetTests.cs +++ b/Assets/UniGLTF/Tests/UniGLTF/AssetTests.cs @@ -33,6 +33,8 @@ namespace UniGLTF var tmp = AssetDatabase.LoadAssetAtPath(assetPath); Assert.Null(tmp); + + AssetDatabase.DeleteAsset(assetPath); } AssetDatabase.Refresh(); diff --git a/Assets/UniGLTF/Tests/UniGLTF/CopyTextureTests.cs b/Assets/UniGLTF/Tests/UniGLTF/CopyTextureTests.cs index 8170541d9..d8304c00b 100644 --- a/Assets/UniGLTF/Tests/UniGLTF/CopyTextureTests.cs +++ b/Assets/UniGLTF/Tests/UniGLTF/CopyTextureTests.cs @@ -1,13 +1,10 @@ using NUnit.Framework; -using UnityEditor; using UnityEngine; namespace UniGLTF { public sealed class CopyTextureTests { - private static string AssetPath = "Assets/VRMShaders/GLTF/IO/Tests"; - private static readonly Color32 Black = new Color32(0, 0, 0, 255); private static readonly Color32 Gray = new Color32(127, 127, 127, 255); private static readonly Color32 White = new Color32(255, 255, 255, 255); @@ -32,7 +29,7 @@ namespace UniGLTF [Test] public void CopyFromNonReadableSRgbPng() { - var nonReadableTex = AssetDatabase.LoadAssetAtPath($"{AssetPath}/4x4_non_readable.png"); + var nonReadableTex = TestAssets.LoadAsset("4x4_non_readable.png"); Assert.False(nonReadableTex.isReadable); var copiedTex = TextureConverter.CopyTexture(nonReadableTex, ColorSpace.sRGB, true, null); var pixels = copiedTex.GetPixels32(miplevel: 0); @@ -46,7 +43,7 @@ namespace UniGLTF [Test] public void CopyFromNonReadableSRgbDds() { - var compressedTex = AssetDatabase.LoadAssetAtPath($"{AssetPath}/4x4_non_readable_compressed.dds"); + var compressedTex = TestAssets.LoadAsset("4x4_non_readable_compressed.dds"); Assert.False(compressedTex.isReadable); var copiedTex = TextureConverter.CopyTexture(compressedTex, ColorSpace.sRGB, true, null); var pixels = copiedTex.GetPixels32(miplevel: 0); @@ -60,7 +57,7 @@ namespace UniGLTF [Test] public void CopyAttributes() { - var src = AssetDatabase.LoadAssetAtPath($"{AssetPath}/4x4_non_readable.png"); + var src = TestAssets.LoadAsset("4x4_non_readable.png"); var dst = TextureConverter.CopyTexture(src, ColorSpace.sRGB, false, null); Assert.AreEqual(src.name, dst.name); Assert.AreEqual(src.anisoLevel, dst.anisoLevel); diff --git a/Assets/UniGLTF/Tests/UniGLTF/EditorTextureSerializerTests.cs b/Assets/UniGLTF/Tests/UniGLTF/EditorTextureSerializerTests.cs index dbc1349e9..a0a128da1 100644 --- a/Assets/UniGLTF/Tests/UniGLTF/EditorTextureSerializerTests.cs +++ b/Assets/UniGLTF/Tests/UniGLTF/EditorTextureSerializerTests.cs @@ -1,18 +1,16 @@ using NUnit.Framework; -using UnityEditor; using UnityEngine; namespace UniGLTF { public sealed class EditorTextureSerializerTests { - private static readonly string AssetPath = "Assets/UniGLTF/Tests/UniGLTF"; private static readonly string SrgbGrayImageName = "4x4_gray_import_as_srgb"; private static readonly string LinearGrayImageName = "4x4_gray_import_as_linear"; private static readonly string NormalMapGrayImageName = "4x4_gray_import_as_normal_map"; - private static readonly Texture2D SrgbGrayTex = AssetDatabase.LoadAssetAtPath($"{AssetPath}/{SrgbGrayImageName}.png"); - private static readonly Texture2D LinearGrayTex = AssetDatabase.LoadAssetAtPath($"{AssetPath}/{LinearGrayImageName}.png"); - private static readonly Texture2D NormalMapGrayTex = AssetDatabase.LoadAssetAtPath($"{AssetPath}/{NormalMapGrayImageName}.png"); + private static readonly Texture2D SrgbGrayTex = TestAssets.LoadAsset($"{SrgbGrayImageName}.png"); + private static readonly Texture2D LinearGrayTex = TestAssets.LoadAsset($"{LinearGrayImageName}.png"); + private static readonly Texture2D NormalMapGrayTex = TestAssets.LoadAsset($"{NormalMapGrayImageName}.png"); private static readonly Color32 JustGray = new Color32(127, 127, 127, 255); private static readonly Color32 SrgbGrayInSrgb = JustGray; private static readonly Color32 SrgbGrayInLinear = ((Color)SrgbGrayInSrgb).linear; @@ -113,23 +111,28 @@ namespace UniGLTF { // Prepare var root = GameObject.CreatePrimitive(PrimitiveType.Cube); - var mat = new Material(Shader.Find("Standard")); + var mat = new Material(Shader.Find(BuiltInStandardMaterialExporter.TargetShaderName)); mat.SetTexture(propertyName, srcTex); root.GetComponentOrThrow().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, - }, textureSerializer: new EditorTextureSerializer())) - { - exporter.Prepare(root); - exporter.Export(); - } + using var exporter = new gltfExporter( + data, + new GltfExportSettings + { + InverseAxis = Axes.X, + ExportOnlyBlendShapePosition = false, + UseSparseAccessorForMorphTarget = false, + DivideVertexBuffer = false, + }, + materialExporter: new BuiltInGltfMaterialExporter(), + textureSerializer: new EditorTextureSerializer() + ); + + exporter.Prepare(root); + exporter.Export(); + var gltf = data.Gltf; Assert.AreEqual(1, gltf.images.Count); var exportedImage = gltf.images[0]; diff --git a/Assets/UniGLTF/Tests/UniGLTF/TestAssets.cs b/Assets/UniGLTF/Tests/UniGLTF/TestAssets.cs new file mode 100644 index 000000000..96319bbf4 --- /dev/null +++ b/Assets/UniGLTF/Tests/UniGLTF/TestAssets.cs @@ -0,0 +1,12 @@ +namespace UniGLTF +{ + public static class TestAssets + { + public static readonly string AssetPath = "Assets/UniGLTF/Tests/Objects"; + + public static T LoadAsset(string filename) where T : UnityEngine.Object + { + return UnityEditor.AssetDatabase.LoadAssetAtPath($"{AssetPath}/{filename}"); + } + } +} \ No newline at end of file diff --git a/Assets/UniGLTF/Tests/UniGLTF/TestAssets.cs.meta b/Assets/UniGLTF/Tests/UniGLTF/TestAssets.cs.meta new file mode 100644 index 000000000..ce8bf83a6 --- /dev/null +++ b/Assets/UniGLTF/Tests/UniGLTF/TestAssets.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 8519ebb2f0f84833a752bb564b59c47c +timeCreated: 1722263712 \ No newline at end of file diff --git a/Assets/UniGLTF/Tests/UniGLTF/TestGltf.cs b/Assets/UniGLTF/Tests/UniGLTF/TestGltf.cs new file mode 100644 index 000000000..36baddf65 --- /dev/null +++ b/Assets/UniGLTF/Tests/UniGLTF/TestGltf.cs @@ -0,0 +1,52 @@ +using UnityEngine; + +namespace UniGLTF +{ + public static class TestGltf + { + public static RuntimeGltfInstance LoadBytesAsBuiltInRP(byte[] bytes) + { + return GltfUtility.LoadBytesAsync( + "", + bytes, + awaitCaller: new ImmediateCaller(), + materialGenerator: new BuiltInGltfMaterialDescriptorGenerator() + ).Result; + } + + public static RuntimeGltfInstance LoadPathAsBuiltInRP(string path) + { + return GltfUtility.LoadAsync( + path, + awaitCaller: new ImmediateCaller(), + materialGenerator: new BuiltInGltfMaterialDescriptorGenerator() + ).Result; + } + + public static ExportingGltfData ExportAsBuiltInRP(GameObject gameObject, GltfExportSettings exportSettings = null) + { + var data = new ExportingGltfData(); + using var exporter = new gltfExporter( + data, + exportSettings ?? new GltfExportSettings(), + progress: new EditorProgress(), + animationExporter: new EditorAnimationExporter(), + materialExporter: new BuiltInGltfMaterialExporter(), + textureSerializer: new EditorTextureSerializer() + ); + exporter.Prepare(gameObject); + exporter.Export(); + + return data; + } + + public static GameObject CreatePrimitiveAsBuiltInRP(PrimitiveType primitiveType) + { + var go = GameObject.CreatePrimitive(primitiveType); + var shader = Shader.Find("Standard"); + var material = new Material(shader); + go.GetComponent().sharedMaterial = material; + return go; + } + } +} \ No newline at end of file diff --git a/Assets/UniGLTF/Tests/UniGLTF/TestGltf.cs.meta b/Assets/UniGLTF/Tests/UniGLTF/TestGltf.cs.meta new file mode 100644 index 000000000..affb261b4 --- /dev/null +++ b/Assets/UniGLTF/Tests/UniGLTF/TestGltf.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 11719ab072944cc2b7c0eaafa0cdff2e +timeCreated: 1722267047 \ No newline at end of file diff --git a/Assets/UniGLTF/Tests/UniGLTF/TextureBytesTests.cs b/Assets/UniGLTF/Tests/UniGLTF/TextureBytesTests.cs index f4ef96a2f..f99019151 100644 --- a/Assets/UniGLTF/Tests/UniGLTF/TextureBytesTests.cs +++ b/Assets/UniGLTF/Tests/UniGLTF/TextureBytesTests.cs @@ -1,17 +1,14 @@ using NUnit.Framework; -using UnityEditor; using UnityEngine; namespace UniGLTF { public class TextureBytesTests { - static string AssetPath = "Assets/VRMShaders/GLTF/IO/Tests"; - [Test] public void NonReadablePng() { - var nonReadableTex = AssetDatabase.LoadAssetAtPath($"{AssetPath}/4x4_non_readable.png"); + var nonReadableTex = TestAssets.LoadAsset("4x4_non_readable.png"); Assert.False(nonReadableTex.isReadable); var (bytes, mime) = new EditorTextureSerializer().ExportBytesWithMime(nonReadableTex, ColorSpace.sRGB); Assert.NotNull(bytes); @@ -20,7 +17,7 @@ namespace UniGLTF [Test] public void NonReadableDds() { - var readonlyTexture = AssetDatabase.LoadAssetAtPath($"{AssetPath}/4x4_non_readable_compressed.dds"); + var readonlyTexture = TestAssets.LoadAsset("4x4_non_readable_compressed.dds"); Assert.False(readonlyTexture.isReadable); var (bytes, mime) = new EditorTextureSerializer().ExportBytesWithMime(readonlyTexture, ColorSpace.sRGB); Assert.NotNull(bytes); diff --git a/Assets/UniGLTF/Tests/UniGLTF/UniGLTFTests.cs b/Assets/UniGLTF/Tests/UniGLTF/UniGLTFTests.cs index 99ad080f6..1368a4fbd 100644 --- a/Assets/UniGLTF/Tests/UniGLTF/UniGLTFTests.cs +++ b/Assets/UniGLTF/Tests/UniGLTF/UniGLTFTests.cs @@ -100,18 +100,17 @@ namespace UniGLTF // export var data = new ExportingGltfData(); + using var exporter = new gltfExporter( + data, + new GltfExportSettings(), + materialExporter: new BuiltInGltfMaterialExporter()); + exporter.Prepare(go); + exporter.Export(); - string json = null; - using (var exporter = new gltfExporter(data, new GltfExportSettings())) - { - exporter.Prepare(go); - exporter.Export(); + // remove empty buffer + data.Gltf.buffers.Clear(); - // remove empty buffer - data.Gltf.buffers.Clear(); - - json = data.Gltf.ToJson(); - } + var json = data.Gltf.ToJson(); // parse using (var parsed = GltfData.CreateFromExportForTest(data)) @@ -353,12 +352,7 @@ namespace UniGLTF [Test] public void GlTFToJsonTest() { - var data = new ExportingGltfData(); - using (var exporter = new gltfExporter(data, new GltfExportSettings())) - { - exporter.Prepare(CreateSimpleScene()); - exporter.Export(); - } + var data = TestGltf.ExportAsBuiltInRP(CreateSimpleScene()); var expected = data.Gltf.ToJson().ParseAsJson(); expected.AddKey(Utf8String.From("meshes")); @@ -565,7 +559,7 @@ namespace UniGLTF { var shader = Shader.Find("Unlit/Color"); - var cubeA = GameObject.CreatePrimitive(PrimitiveType.Cube); + var cubeA = TestGltf.CreatePrimitiveAsBuiltInRP(PrimitiveType.Cube); { cubeA.transform.SetParent(go.transform); var material = new Material(shader); @@ -586,16 +580,8 @@ namespace UniGLTF } // export - var data = new ExportingGltfData(); + var data = TestGltf.ExportAsBuiltInRP(go); var gltf = data.Gltf; - var json = default(string); - using (var exporter = new gltfExporter(data, new GltfExportSettings())) - { - exporter.Prepare(go); - exporter.Export(); - - json = gltf.ToJson(); - } Assert.AreEqual(2, gltf.meshes.Count); @@ -658,22 +644,14 @@ namespace UniGLTF try { { - var cube = GameObject.CreatePrimitive(PrimitiveType.Cube); + var cube = TestGltf.CreatePrimitiveAsBuiltInRP(PrimitiveType.Cube); cube.transform.SetParent(go.transform); UnityEngine.Object.DestroyImmediate(cube.GetComponent()); } // export - var data = new ExportingGltfData(); + var data = TestGltf.ExportAsBuiltInRP(go); var gltf = data.Gltf; - string json; - using (var exporter = new gltfExporter(data, new GltfExportSettings())) - { - exporter.Prepare(go); - exporter.Export(); - - json = gltf.ToJson(); - } Assert.AreEqual(0, gltf.meshes.Count); Assert.AreEqual(1, gltf.nodes.Count); @@ -682,7 +660,7 @@ namespace UniGLTF // import using (var parsed = GltfData.CreateFromExportForTest(data)) { - using (var context = new ImporterContext(parsed)) + using (var context = new ImporterContext(parsed, materialGenerator: new BuiltInGltfMaterialDescriptorGenerator())) using (var loaded = context.Load()) { Assert.AreEqual(1, loaded.transform.GetChildren().Count()); @@ -708,14 +686,14 @@ namespace UniGLTF try { { - var child = GameObject.CreatePrimitive(PrimitiveType.Cube); + var child = TestGltf.CreatePrimitiveAsBuiltInRP(PrimitiveType.Cube); child.transform.SetParent(root.transform); // remove MeshFilter Component.DestroyImmediate(child.GetComponent()); } { - var child = GameObject.CreatePrimitive(PrimitiveType.Cube); + var child = TestGltf.CreatePrimitiveAsBuiltInRP(PrimitiveType.Cube); child.transform.SetParent(root.transform); // set null child.GetComponent().sharedMesh = null; @@ -727,16 +705,9 @@ namespace UniGLTF Assert.True(vs.All(x => x.CanExport)); // export - var data = new ExportingGltfData(); + var data = TestGltf.ExportAsBuiltInRP(root); var gltf = data.Gltf; - string json; - using (var exporter = new gltfExporter(data, new GltfExportSettings())) - { - exporter.Prepare(root); - exporter.Export(); - - json = gltf.ToJson(); - } + var json = gltf.ToJson(); Assert.AreEqual(0, gltf.meshes.Count); Assert.AreEqual(2, gltf.nodes.Count); @@ -770,6 +741,42 @@ namespace UniGLTF } } + // + // https://github.com/vrm-c/UniVRM/pull/2413 + // + [Test] + public void ExportingMeshByteLengthTest() + { + var validator = ScriptableObject.CreateInstance(); + var root = new GameObject("root"); + try + { + { + var child = TestGltf.CreatePrimitiveAsBuiltInRP(PrimitiveType.Cube); + child.transform.SetParent(root.transform); + } + // export + var data = TestGltf.ExportAsBuiltInRP(root); + var gltf = data.Gltf; + // cube + var expected = + // pos + (4*3)*24 + // normal + +(4*3)*24 + // uv + +(4*2)*24 + // indices + + 4 * 36; + Assert.AreEqual(expected, gltf.buffers[0].byteLength); + } + finally + { + GameObject.DestroyImmediate(root); + ScriptableObject.DestroyImmediate(validator); + } + } + [Serializable] class CantConstruct { diff --git a/Assets/UniGLTF/UniUnlit/Runtime/UniUnlitContext.cs b/Assets/UniGLTF/UniUnlit/Runtime/UniUnlitContext.cs new file mode 100644 index 000000000..5f3573aba --- /dev/null +++ b/Assets/UniGLTF/UniUnlit/Runtime/UniUnlitContext.cs @@ -0,0 +1,80 @@ +using UnityEngine; + +namespace UniGLTF.UniUnlit +{ + public class UniUnlitContext + { + public Material Material { get; } + public bool UnsafeEditMode { get; set; } = false; + + public UniUnlitContext(Material material) + { + Material = material; + } + + public UniUnlitRenderMode RenderMode + { + get => UniUnlitUtil.GetRenderMode(Material); + set + { + UniUnlitUtil.SetRenderMode(Material, value); + if (!UnsafeEditMode) UniUnlitUtil.ValidateProperties(Material, isRenderModeChangedByUser: true); + } + } + + public UniUnlitCullMode CullMode + { + get => UniUnlitUtil.GetCullMode(Material); + set + { + UniUnlitUtil.SetCullMode(Material, value); + if (!UnsafeEditMode) UniUnlitUtil.ValidateProperties(Material); + } + } + + public UniUnlitVertexColorBlendOp VColBlendMode + { + get => UniUnlitUtil.GetVColBlendMode(Material); + set + { + UniUnlitUtil.SetVColBlendMode(Material, value); + if (!UnsafeEditMode) UniUnlitUtil.ValidateProperties(Material); + } + } + + public Color MainColorSrgb + { + get => Material.GetColor(UniUnlitUtil.PropNameColor); + set => Material.SetColor(UniUnlitUtil.PropNameColor, value); + } + + public Texture MainTexture + { + get => Material.GetTexture(UniUnlitUtil.PropNameMainTex); + set => Material.SetTexture(UniUnlitUtil.PropNameMainTex, value); + } + + public Vector2 MainTextureOffset + { + get => Material.GetTextureOffset(UniUnlitUtil.PropNameMainTex); + set => Material.SetTextureOffset(UniUnlitUtil.PropNameMainTex, value); + } + + public Vector2 MainTextureScale + { + get => Material.GetTextureScale(UniUnlitUtil.PropNameMainTex); + set => Material.SetTextureScale(UniUnlitUtil.PropNameMainTex, value); + } + + public float Cutoff + { + get => Material.GetFloat(UniUnlitUtil.PropNameCutoff); + set => Material.SetFloat(UniUnlitUtil.PropNameCutoff, value); + } + + public void Validate() + { + UniUnlitUtil.ValidateProperties(Material, isRenderModeChangedByUser: true); + } + } +} \ No newline at end of file diff --git a/Assets/UniGLTF/UniUnlit/Runtime/UniUnlitContext.cs.meta b/Assets/UniGLTF/UniUnlit/Runtime/UniUnlitContext.cs.meta new file mode 100644 index 000000000..77c89e884 --- /dev/null +++ b/Assets/UniGLTF/UniUnlit/Runtime/UniUnlitContext.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 57963fbf465047bf83ed829f8a0022d3 +timeCreated: 1722613449 \ No newline at end of file diff --git a/Assets/UniGLTF/package.json b/Assets/UniGLTF/package.json index e4822d40d..a717e6305 100644 --- a/Assets/UniGLTF/package.json +++ b/Assets/UniGLTF/package.json @@ -1,6 +1,6 @@ { "name": "com.vrmc.gltf", - "version": "0.124.2", + "version": "0.125.0", "displayName": "UniGLTF", "description": "GLTF importer and exporter", "unity": "2021.3", diff --git a/Assets/VRM/Editor/Format/VRMEditorExporter.cs b/Assets/VRM/Editor/Format/VRMEditorExporter.cs index c4489d7a4..6e48f7d88 100644 --- a/Assets/VRM/Editor/Format/VRMEditorExporter.cs +++ b/Assets/VRM/Editor/Format/VRMEditorExporter.cs @@ -16,12 +16,17 @@ namespace VRM /// /// 出力先 /// エクスポート設定 - public static byte[] Export(GameObject exportRoot, VRMMetaObject meta, VRMExportSettings settings) + public static byte[] Export( + GameObject exportRoot, + VRMMetaObject meta, + VRMExportSettings settings, + IMaterialExporter materialExporter = null + ) { List destroy = new List(); try { - return Export(exportRoot, meta, settings, destroy); + return Export(exportRoot, meta, settings, materialExporter, destroy); } finally { @@ -143,9 +148,12 @@ namespace VRM /// /// /// 作業が終わったらDestoryするべき一時オブジェクト - static byte[] Export(GameObject exportRoot, VRMMetaObject meta, - VRMExportSettings settings, - List destroy) + private static byte[] Export( + GameObject exportRoot, + VRMMetaObject meta, + VRMExportSettings settings, + IMaterialExporter materialExporter, + List destroy) { var target = exportRoot; @@ -227,6 +235,7 @@ namespace VRM var gltfExportSettings = settings.GltfExportSettings; using (var exporter = new VRMExporter(data, gltfExportSettings, animationExporter: settings.KeepAnimation ? new EditorAnimationExporter() : null, + materialExporter: materialExporter, textureSerializer: new EditorTextureSerializer())) { exporter.Prepare(target); diff --git a/Assets/VRM/Editor/Format/vrmAssetPostprocessor.cs b/Assets/VRM/Editor/Format/vrmAssetPostprocessor.cs index 4edcfa423..688e7ffc5 100644 --- a/Assets/VRM/Editor/Format/vrmAssetPostprocessor.cs +++ b/Assets/VRM/Editor/Format/vrmAssetPostprocessor.cs @@ -76,10 +76,11 @@ namespace VRM var map = texturePaths .Select(x => x.LoadAsset()) .ToDictionary(x => new SubAssetKey(x), x => x as UnityEngine.Object); + var settings = new ImporterContextSettings(); // 確実に Dispose するために敢えて再パースしている using (var data = new GlbFileParser(vrmPath).Parse()) - using (var context = new VRMImporterContext(new VRMData(data), externalObjectMap: map, loadAnimation: true)) + using (var context = new VRMImporterContext(new VRMData(data), externalObjectMap: map, settings: settings)) { var editor = new VRMEditorImporterContext(context, prefabPath); foreach (var textureInfo in context.TextureDescriptorGenerator.Get().GetEnumerable()) diff --git a/Assets/VRM/Runtime/SpringBone/TransformExtensions.cs b/Assets/VRM/Runtime/Extensions/TransformExtensions.cs similarity index 100% rename from Assets/VRM/Runtime/SpringBone/TransformExtensions.cs rename to Assets/VRM/Runtime/Extensions/TransformExtensions.cs diff --git a/Assets/VRM/Runtime/SpringBone/TransformExtensions.cs.meta b/Assets/VRM/Runtime/Extensions/TransformExtensions.cs.meta similarity index 100% rename from Assets/VRM/Runtime/SpringBone/TransformExtensions.cs.meta rename to Assets/VRM/Runtime/Extensions/TransformExtensions.cs.meta diff --git a/Assets/VRM/Runtime/IO/MaterialIO/BuiltInRP/Import/BuiltInVrmMaterialDescriptorGenerator.cs b/Assets/VRM/Runtime/IO/MaterialIO/BuiltInRP/Import/BuiltInVrmMaterialDescriptorGenerator.cs index aae706af3..b48387cd0 100644 --- a/Assets/VRM/Runtime/IO/MaterialIO/BuiltInRP/Import/BuiltInVrmMaterialDescriptorGenerator.cs +++ b/Assets/VRM/Runtime/IO/MaterialIO/BuiltInRP/Import/BuiltInVrmMaterialDescriptorGenerator.cs @@ -41,21 +41,13 @@ namespace VRM } // fallback - Debug.LogWarning($"fallback"); - return new MaterialDescriptor( - GltfMaterialImportUtils.ImportMaterialName(i, null), - BuiltInGltfPbrMaterialImporter.Shader, - null, - new Dictionary(), - new Dictionary(), - new Dictionary(), - new Dictionary(), - new Action[]{}); + if (Symbols.VRM_DEVELOP) + { + Debug.LogWarning($"material: {i} out of range. fallback"); + } + return GetGltfDefault(GltfMaterialImportUtils.ImportMaterialName(i, null)); } - public MaterialDescriptor GetGltfDefault() - { - return BuiltInGltfDefaultMaterialImporter.CreateParam(); - } + public MaterialDescriptor GetGltfDefault(string materialName = null) => BuiltInGltfDefaultMaterialImporter.CreateParam(materialName); } } diff --git a/Assets/VRM/Runtime/IO/MaterialIO/URP/Import/UrpVrmMaterialDescriptorGenerator.cs b/Assets/VRM/Runtime/IO/MaterialIO/URP/Import/UrpVrmMaterialDescriptorGenerator.cs index 85f1fae2d..10da02bdd 100644 --- a/Assets/VRM/Runtime/IO/MaterialIO/URP/Import/UrpVrmMaterialDescriptorGenerator.cs +++ b/Assets/VRM/Runtime/IO/MaterialIO/URP/Import/UrpVrmMaterialDescriptorGenerator.cs @@ -9,6 +9,9 @@ namespace VRM { private readonly glTF_VRM_extensions _vrm; + public UrpGltfPbrMaterialImporter PbrMaterialImporter { get; } = new(); + public UrpGltfDefaultMaterialImporter DefaultMaterialImporter { get; } = new(); + public UrpVrmMaterialDescriptorGenerator(glTF_VRM_extensions vrm) { _vrm = vrm; @@ -20,26 +23,16 @@ namespace VRM // unlit "UniUnlit" work in URP if (BuiltInGltfUnlitMaterialImporter.TryCreateParam(data, i, out var matDesc)) return matDesc; // pbr "Standard" to "Universal Render Pipeline/Lit" - if (UrpGltfPbrMaterialImporter.TryCreateParam(data, i, out matDesc)) return matDesc; - // fallback + if (PbrMaterialImporter.TryCreateParam(data, i, out matDesc)) return matDesc; + + // NOTE: Fallback to default material if (Symbols.VRM_DEVELOP) { Debug.LogWarning($"material: {i} out of range. fallback"); } - return new MaterialDescriptor( - GltfMaterialImportUtils.ImportMaterialName(i, null), - UrpGltfPbrMaterialImporter.Shader, - null, - new Dictionary(), - new Dictionary(), - new Dictionary(), - new Dictionary(), - new Action[]{}); + return GetGltfDefault(GltfMaterialImportUtils.ImportMaterialName(i, null)); } - public MaterialDescriptor GetGltfDefault() - { - return UrpGltfDefaultMaterialImporter.CreateParam(); - } + public MaterialDescriptor GetGltfDefault(string materialName = null) => DefaultMaterialImporter.CreateParam(materialName); } } diff --git a/Assets/VRM/Runtime/IO/MaterialIO/VrmMaterialDescriptorGeneratorUtility.cs b/Assets/VRM/Runtime/IO/MaterialIO/VrmMaterialDescriptorGeneratorUtility.cs index f13e9e92a..6aa838ca1 100644 --- a/Assets/VRM/Runtime/IO/MaterialIO/VrmMaterialDescriptorGeneratorUtility.cs +++ b/Assets/VRM/Runtime/IO/MaterialIO/VrmMaterialDescriptorGeneratorUtility.cs @@ -6,7 +6,12 @@ namespace VRM { public static IMaterialDescriptorGenerator GetValidVrmMaterialDescriptorGenerator(glTF_VRM_extensions vrm) { - return RenderPipelineUtility.GetRenderPipelineType() switch + return GetVrmMaterialDescriptorGenerator(vrm, RenderPipelineUtility.GetRenderPipelineType()); + } + + public static IMaterialDescriptorGenerator GetVrmMaterialDescriptorGenerator(glTF_VRM_extensions vrm, RenderPipelineTypes renderPipelineType) + { + return renderPipelineType switch { RenderPipelineTypes.UniversalRenderPipeline => new UrpVrmMaterialDescriptorGenerator(vrm), RenderPipelineTypes.BuiltinRenderPipeline => new BuiltInVrmMaterialDescriptorGenerator(vrm), diff --git a/Assets/VRM/Runtime/IO/VRMImporterContext.cs b/Assets/VRM/Runtime/IO/VRMImporterContext.cs index 642c40917..a3cc8f4af 100644 --- a/Assets/VRM/Runtime/IO/VRMImporterContext.cs +++ b/Assets/VRM/Runtime/IO/VRMImporterContext.cs @@ -25,12 +25,11 @@ namespace VRM IReadOnlyDictionary externalObjectMap = null, ITextureDeserializer textureDeserializer = null, IMaterialDescriptorGenerator materialGenerator = null, - bool loadAnimation = false) - : base(data.Data, externalObjectMap, textureDeserializer, materialGenerator ?? VrmMaterialDescriptorGeneratorUtility.GetValidVrmMaterialDescriptorGenerator(data.VrmExtension)) + ImporterContextSettings settings = null) + : base(data.Data, externalObjectMap, textureDeserializer, materialGenerator ?? VrmMaterialDescriptorGeneratorUtility.GetValidVrmMaterialDescriptorGenerator(data.VrmExtension), settings ?? new ImporterContextSettings(false)) { _data = data; TextureDescriptorGenerator = new VrmTextureDescriptorGenerator(Data, VRM); - LoadAnimation = loadAnimation; } #region OnLoad diff --git a/Assets/VRM/Runtime/IO/VrmUtility.cs b/Assets/VRM/Runtime/IO/VrmUtility.cs index 34f08bea6..8ba66c562 100644 --- a/Assets/VRM/Runtime/IO/VrmUtility.cs +++ b/Assets/VRM/Runtime/IO/VrmUtility.cs @@ -39,11 +39,12 @@ namespace VRM { materialGen = materialGeneratorCallback(vrm.VrmExtension); } + var importerContextSettings = new ImporterContextSettings(loadAnimation); using (var loader = new VRMImporterContext( vrm, textureDeserializer: textureDeserializer, materialGenerator: materialGen, - loadAnimation: loadAnimation)) + settings: importerContextSettings)) { if (metaCallback != null) { @@ -96,11 +97,12 @@ namespace VRM { materialGen = materialGeneratorCallback(vrm.VrmExtension); } + var importerContextSettings = new ImporterContextSettings(loadAnimation: loadAnimation); using (var loader = new VRMImporterContext( vrm, textureDeserializer: textureDeserializer, materialGenerator: materialGen, - loadAnimation: loadAnimation)) + settings: importerContextSettings)) { if (metaCallback != null) { diff --git a/Assets/VRM/Runtime/SpringBone/Logic.meta b/Assets/VRM/Runtime/SpringBone/Logic.meta new file mode 100644 index 000000000..778166f77 --- /dev/null +++ b/Assets/VRM/Runtime/SpringBone/Logic.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1b3d9c467d3da3e4aa800f2a9229768c +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/VRM/Runtime/SpringBone/Logic/SceneInfo.cs b/Assets/VRM/Runtime/SpringBone/Logic/SceneInfo.cs new file mode 100644 index 000000000..546673013 --- /dev/null +++ b/Assets/VRM/Runtime/SpringBone/Logic/SceneInfo.cs @@ -0,0 +1,12 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace VRM.SpringBone +{ + struct SceneInfo + { + public IReadOnlyList RootBones; + public Transform Center; + public VRMSpringBoneColliderGroup[] ColliderGroups; + } +} \ No newline at end of file diff --git a/Assets/VRM/Runtime/SpringBone/Logic/SceneInfo.cs.meta b/Assets/VRM/Runtime/SpringBone/Logic/SceneInfo.cs.meta new file mode 100644 index 000000000..982e67800 --- /dev/null +++ b/Assets/VRM/Runtime/SpringBone/Logic/SceneInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1f9f3d46865885b4a8d559a5d962db5a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/VRM/Runtime/SpringBone/Logic/SphereCollider.cs b/Assets/VRM/Runtime/SpringBone/Logic/SphereCollider.cs new file mode 100644 index 000000000..a59c36e8c --- /dev/null +++ b/Assets/VRM/Runtime/SpringBone/Logic/SphereCollider.cs @@ -0,0 +1,18 @@ +using UnityEngine; + +namespace VRM.SpringBone +{ + struct SphereCollider + { + public readonly Vector3 Position; + public readonly float Radius; + + public SphereCollider(Transform transform, VRMSpringBoneColliderGroup.SphereCollider collider) + { + Position = transform.TransformPoint(collider.Offset); + var ls = transform.lossyScale; + var scale = Mathf.Max(Mathf.Max(ls.x, ls.y), ls.z); + Radius = scale * collider.Radius; + } + } +} \ No newline at end of file diff --git a/Assets/VRM/Runtime/SpringBone/Logic/SphereCollider.cs.meta b/Assets/VRM/Runtime/SpringBone/Logic/SphereCollider.cs.meta new file mode 100644 index 000000000..998c40f98 --- /dev/null +++ b/Assets/VRM/Runtime/SpringBone/Logic/SphereCollider.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 102ef8d07b335ee42b6a198b5657ef80 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJoint.cs b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJoint.cs new file mode 100644 index 000000000..d15e48201 --- /dev/null +++ b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJoint.cs @@ -0,0 +1,129 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace VRM.SpringBone +{ + /// + /// original from + /// http://rocketjump.skr.jp/unity3d/109/ + /// + class SpringBoneJoint + { + Transform m_transform; + public Transform Head => m_transform; + + private Vector3 m_boneAxis; + private Vector3 m_currentTail; + + private readonly float m_length; + private Vector3 m_localDir; + private Vector3 m_prevTail; + + public SpringBoneJoint(Transform center, Transform transform, Vector3 localChildPosition) + { + m_transform = transform; + var worldChildPosition = m_transform.TransformPoint(localChildPosition); + m_currentTail = center != null + ? center.InverseTransformPoint(worldChildPosition) + : worldChildPosition; + m_prevTail = m_currentTail; + LocalRotation = transform.localRotation; + m_boneAxis = localChildPosition.normalized; + m_length = localChildPosition.magnitude; + } + + public Vector3 Tail => m_transform.localToWorldMatrix.MultiplyPoint(m_boneAxis * m_length); + + private Quaternion LocalRotation { get; } + + float m_radius; + public void SetRadius(float radius) + { + m_radius = radius * m_transform.UniformedLossyScale(); + } + + private Quaternion ParentRotation => + m_transform.parent != null + ? m_transform.parent.rotation + : Quaternion.identity; + + public void Update(Transform center, + float stiffnessForce, float dragForce, Vector3 external, + List colliders) + { + var currentTail = center != null + ? center.TransformPoint(m_currentTail) + : m_currentTail; + var prevTail = center != null + ? center.TransformPoint(m_prevTail) + : m_prevTail; + + // verlet積分で次の位置を計算 + var nextTail = currentTail + + (currentTail - prevTail) * (1.0f - dragForce) // 前フレームの移動を継続する(減衰もあるよ) + + ParentRotation * LocalRotation * m_boneAxis * stiffnessForce // 親の回転による子ボーンの移動目標 + + external; // 外力による移動量 + + // 長さをboneLengthに強制 + var position = m_transform.position; + nextTail = position + (nextTail - position).normalized * m_length; + + // Collisionで移動 + nextTail = Collision(colliders, nextTail); + + m_prevTail = center != null + ? center.InverseTransformPoint(currentTail) + : currentTail; + + m_currentTail = center != null + ? center.InverseTransformPoint(nextTail) + : nextTail; + + //回転を適用 + m_transform.rotation = ApplyRotation(nextTail); + } + + protected virtual Quaternion ApplyRotation(Vector3 nextTail) + { + var rotation = ParentRotation * LocalRotation; + return Quaternion.FromToRotation(rotation * m_boneAxis, + nextTail - m_transform.position) * rotation; + } + + protected virtual Vector3 Collision(List colliders, Vector3 nextTail) + { + foreach (var collider in colliders) + { + var r = m_radius + collider.Radius; + if (Vector3.SqrMagnitude(nextTail - collider.Position) <= (r * r)) + { + // ヒット。Colliderの半径方向に押し出す + var normal = (nextTail - collider.Position).normalized; + var posFromCollider = collider.Position + normal * (m_radius + collider.Radius); + // 長さをboneLengthに強制 + nextTail = m_transform.position + (posFromCollider - m_transform.position).normalized * m_length; + } + } + return nextTail; + } + + public void DrawGizmo(Transform center, Color color) + { + var currentTail = center != null + ? center.TransformPoint(m_currentTail) + : m_currentTail; + var prevTail = center != null + ? center.TransformPoint(m_prevTail) + : m_prevTail; + + Gizmos.color = Color.gray; + Gizmos.DrawLine(currentTail, prevTail); + Gizmos.DrawWireSphere(prevTail, m_radius); + + Gizmos.color = color; + Gizmos.DrawLine(currentTail, m_transform.position); + Gizmos.DrawWireSphere(currentTail, m_radius); + } + } + +} \ No newline at end of file diff --git a/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJoint.cs.meta b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJoint.cs.meta new file mode 100644 index 000000000..70dd7502d --- /dev/null +++ b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJoint.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2602939771f9eb2428b140e10fa899f2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSettings.cs b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSettings.cs new file mode 100644 index 000000000..bc6209047 --- /dev/null +++ b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSettings.cs @@ -0,0 +1,13 @@ +using UnityEngine; + +namespace VRM.SpringBone +{ + struct SpringBoneSettings + { + public float StiffnessForce; + public Vector3 GravityDir; + public float GravityPower; + public float HitRadius; + public float DragForce; + } +} \ No newline at end of file diff --git a/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSettings.cs.meta b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSettings.cs.meta new file mode 100644 index 000000000..b02b7795e --- /dev/null +++ b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSettings.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c979a822d9cd3754db84ce10c42f3b56 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSystem.cs b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSystem.cs new file mode 100644 index 000000000..98d5d433d --- /dev/null +++ b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSystem.cs @@ -0,0 +1,158 @@ +using System.Collections.Generic; +using System.Linq; +using UnityEngine; + +namespace VRM.SpringBone +{ + /// + /// 同じ設定のスプリングをまとめて処理する。 + /// + /// root o-o-o-x tail + /// + /// [vrm0] tail は 7cm 遠にダミーの joint があるようにふるまう。 + /// + /// + class SpringBoneSystem + { + Dictionary m_initialLocalRotationMap; + List m_joints = new(); + List m_colliders = new(); + + public void SetLocalRotationsIdentity() + { + foreach (var verlet in m_joints) verlet.Head.localRotation = Quaternion.identity; + } + + public void Setup(SceneInfo scene, bool force) + { + if (force || m_initialLocalRotationMap == null) + { + m_initialLocalRotationMap = new Dictionary(); + } + else + { + foreach (var kv in m_initialLocalRotationMap) kv.Key.localRotation = kv.Value; + m_initialLocalRotationMap.Clear(); + } + m_joints.Clear(); + + foreach (var go in scene.RootBones) + { + if (go != null) + { + foreach (var x in go.transform.GetComponentsInChildren(true)) m_initialLocalRotationMap[x] = x.localRotation; + + SetupRecursive(scene.Center, go); + } + } + } + + private static IEnumerable GetChildren(Transform parent) + { + for (var i = 0; i < parent.childCount; ++i) yield return parent.GetChild(i); + } + + private void SetupRecursive(Transform center, Transform parent) + { + Vector3 localPosition = default; + Vector3 scale = default; + if (parent.childCount == 0) + { + // 子ノードが無い。7cm 固定 + var delta = parent.position - parent.parent.position; + var childPosition = parent.position + delta.normalized * 0.07f * parent.UniformedLossyScale(); + localPosition = parent.worldToLocalMatrix.MultiplyPoint(childPosition); // cancel scale + scale = parent.lossyScale; + } + else + { + var firstChild = GetChildren(parent).First(); + localPosition = firstChild.localPosition; + scale = firstChild.lossyScale; + } + m_joints.Add(new SpringBone.SpringBoneJoint(center, parent, + new Vector3( + localPosition.x * scale.x, + localPosition.y * scale.y, + localPosition.z * scale.z + ))) + ; + + foreach (Transform child in parent) SetupRecursive(center, child); + } + + + public void UpdateProcess(float deltaTime, + SceneInfo scene, + SpringBoneSettings settings + ) + { + if (m_joints == null || m_joints.Count == 0) + { + if (scene.RootBones == null) return; + Setup(scene, false); + } + + m_colliders.Clear(); + if (scene.ColliderGroups != null) + { + foreach (var group in scene.ColliderGroups) + { + if (group != null) + { + foreach (var collider in group.Colliders) + { + m_colliders.Add(new SphereCollider(group.transform, collider)); + } + } + } + } + + var stiffness = settings.StiffnessForce * deltaTime; + var external = settings.GravityDir * (settings.GravityPower * deltaTime); + + foreach (var verlet in m_joints) + { + verlet.SetRadius(settings.HitRadius); + verlet.Update(scene.Center, + stiffness, + settings.DragForce, + external, + m_colliders + ); + } + } + + public void PlayingGizmo(Transform m_center, Color m_gizmoColor) + { + foreach (var verlet in m_joints) + { + verlet.DrawGizmo(m_center, m_gizmoColor); + } + } + + public void EditorGizmo(Transform head, float m_hitRadius) + { + Vector3 childPosition; + Vector3 scale; + if (head.childCount == 0) + { + // 子ノードが無い。7cm 固定 + var delta = head.position - head.parent.position; + childPosition = head.position + delta.normalized * 0.07f * head.UniformedLossyScale(); + scale = head.lossyScale; + } + else + { + var firstChild = GetChildren(head).First(); + childPosition = firstChild.position; + scale = firstChild.lossyScale; + } + + Gizmos.DrawLine(head.position, childPosition); + Gizmos.DrawWireSphere(childPosition, m_hitRadius * scale.x); + + foreach (Transform child in head) EditorGizmo(child, m_hitRadius); + } + } +} \ No newline at end of file diff --git a/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSystem.cs.meta b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSystem.cs.meta new file mode 100644 index 000000000..9ba5abade --- /dev/null +++ b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSystem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9cc72abc9e20895419ca606484cc7dc0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/VRM/Runtime/SpringBone/VRMSpringBone.cs b/Assets/VRM/Runtime/SpringBone/VRMSpringBone.cs index 5e9d8c7d0..2e971d2cc 100644 --- a/Assets/VRM/Runtime/SpringBone/VRMSpringBone.cs +++ b/Assets/VRM/Runtime/SpringBone/VRMSpringBone.cs @@ -1,7 +1,5 @@ using System.Collections.Generic; -using System.Linq; using UnityEngine; -using UniGLTF; namespace VRM { @@ -13,30 +11,16 @@ namespace VRM // [RequireComponent(typeof(VCIObject))] public sealed class VRMSpringBone : MonoBehaviour { - [SerializeField] - public string m_comment; - + [SerializeField] public string m_comment; [SerializeField] private Color m_gizmoColor = Color.yellow; - - [SerializeField] - public float m_stiffnessForce = 1.0f; - + [SerializeField] public float m_stiffnessForce = 1.0f; [SerializeField] public float m_gravityPower; - [SerializeField] public Vector3 m_gravityDir = new Vector3(0, -1.0f, 0); - [SerializeField][Range(0, 1)] public float m_dragForce = 0.4f; - [SerializeField] public Transform m_center; - [SerializeField] public List RootBones = new List(); - Dictionary m_initialLocalRotationMap; - - [SerializeField] - public float m_hitRadius = 0.02f; - - [SerializeField] - public VRMSpringBoneColliderGroup[] ColliderGroups; + [SerializeField] public float m_hitRadius = 0.02f; + [SerializeField] public VRMSpringBoneColliderGroup[] ColliderGroups; public enum SpringBoneUpdateType { @@ -44,211 +28,39 @@ namespace VRM FixedUpdate, Manual, } - [SerializeField] - public SpringBoneUpdateType m_updateType = SpringBoneUpdateType.LateUpdate; + [SerializeField] public SpringBoneUpdateType m_updateType = SpringBoneUpdateType.LateUpdate; - /// - /// original from - /// http://rocketjump.skr.jp/unity3d/109/ - /// - private class VRMSpringBoneLogic - { - Transform m_transform; - public Transform Head => m_transform; - - private Vector3 m_boneAxis; - private Vector3 m_currentTail; - - private readonly float m_length; - private Vector3 m_localDir; - private Vector3 m_prevTail; - - public VRMSpringBoneLogic(Transform center, Transform transform, Vector3 localChildPosition) - { - m_transform = transform; - var worldChildPosition = m_transform.TransformPoint(localChildPosition); - m_currentTail = center != null - ? center.InverseTransformPoint(worldChildPosition) - : worldChildPosition; - m_prevTail = m_currentTail; - LocalRotation = transform.localRotation; - m_boneAxis = localChildPosition.normalized; - m_length = localChildPosition.magnitude; - } - - public Vector3 Tail => m_transform.localToWorldMatrix.MultiplyPoint(m_boneAxis * m_length); - - private Quaternion LocalRotation { get; } - - float m_radius; - public void SetRadius(float radius) - { - m_radius = radius * m_transform.UniformedLossyScale(); - } - - private Quaternion ParentRotation => - m_transform.parent != null - ? m_transform.parent.rotation - : Quaternion.identity; - - public void Update(Transform center, - float stiffnessForce, float dragForce, Vector3 external, - List colliders) - { - var currentTail = center != null - ? center.TransformPoint(m_currentTail) - : m_currentTail; - var prevTail = center != null - ? center.TransformPoint(m_prevTail) - : m_prevTail; - - // verlet積分で次の位置を計算 - var nextTail = currentTail - + (currentTail - prevTail) * (1.0f - dragForce) // 前フレームの移動を継続する(減衰もあるよ) - + ParentRotation * LocalRotation * m_boneAxis * stiffnessForce // 親の回転による子ボーンの移動目標 - + external; // 外力による移動量 - - // 長さをboneLengthに強制 - var position = m_transform.position; - nextTail = position + (nextTail - position).normalized * m_length; - - // Collisionで移動 - nextTail = Collision(colliders, nextTail); - - m_prevTail = center != null - ? center.InverseTransformPoint(currentTail) - : currentTail; - - m_currentTail = center != null - ? center.InverseTransformPoint(nextTail) - : nextTail; - - //回転を適用 - m_transform.rotation = ApplyRotation(nextTail); - } - - protected virtual Quaternion ApplyRotation(Vector3 nextTail) - { - var rotation = ParentRotation * LocalRotation; - return Quaternion.FromToRotation(rotation * m_boneAxis, - nextTail - m_transform.position) * rotation; - } - - protected virtual Vector3 Collision(List colliders, Vector3 nextTail) - { - foreach (var collider in colliders) - { - var r = m_radius + collider.Radius; - if (Vector3.SqrMagnitude(nextTail - collider.Position) <= (r * r)) - { - // ヒット。Colliderの半径方向に押し出す - var normal = (nextTail - collider.Position).normalized; - var posFromCollider = collider.Position + normal * (m_radius + collider.Radius); - // 長さをboneLengthに強制 - nextTail = m_transform.position + (posFromCollider - m_transform.position).normalized * m_length; - } - } - return nextTail; - } - - public void DrawGizmo(Transform center, Color color) - { - var currentTail = center != null - ? center.TransformPoint(m_currentTail) - : m_currentTail; - var prevTail = center != null - ? center.TransformPoint(m_prevTail) - : m_prevTail; - - Gizmos.color = Color.gray; - Gizmos.DrawLine(currentTail, prevTail); - Gizmos.DrawWireSphere(prevTail, m_radius); - - Gizmos.color = color; - Gizmos.DrawLine(currentTail, m_transform.position); - Gizmos.DrawWireSphere(currentTail, m_radius); - } - } - - List m_verlet = new List(); + SpringBone.SpringBoneSystem m_system = new(); void Awake() { Setup(); } + SpringBone.SceneInfo Scene => new SpringBone.SceneInfo { RootBones = RootBones, Center = m_center }; + SpringBone.SpringBoneSettings Settings => new SpringBone.SpringBoneSettings + { + StiffnessForce = m_stiffnessForce, + GravityDir = m_gravityDir, + GravityPower = m_gravityPower, + HitRadius = m_hitRadius, + DragForce = m_dragForce, + }; + [ContextMenu("Reset bones")] public void Setup(bool force = false) { if (RootBones != null) { - if (force || m_initialLocalRotationMap == null) - { - m_initialLocalRotationMap = new Dictionary(); - } - else - { - foreach (var kv in m_initialLocalRotationMap) kv.Key.localRotation = kv.Value; - m_initialLocalRotationMap.Clear(); - } - m_verlet.Clear(); - - foreach (var go in RootBones) - { - if (go != null) - { - foreach (var x in go.transform.GetComponentsInChildren(true)) m_initialLocalRotationMap[x] = x.localRotation; - - SetupRecursive(m_center, go); - } - } + m_system.Setup(Scene, force); } } - public void SetLocalRotationsIdentity() - { - foreach (var verlet in m_verlet) verlet.Head.localRotation = Quaternion.identity; - } - - private static IEnumerable GetChildren(Transform parent) - { - for (var i = 0; i < parent.childCount; ++i) yield return parent.GetChild(i); - } - - private void SetupRecursive(Transform center, Transform parent) - { - Vector3 localPosition = default; - Vector3 scale = default; - if (parent.childCount == 0) - { - // 子ノードが無い。7cm 固定 - var delta = parent.position - parent.parent.position; - var childPosition = parent.position + delta.normalized * 0.07f * parent.UniformedLossyScale(); - localPosition = parent.worldToLocalMatrix.MultiplyPoint(childPosition); // cancel scale - scale = parent.lossyScale; - } - else - { - var firstChild = GetChildren(parent).First(); - localPosition = firstChild.localPosition; - scale = firstChild.lossyScale; - } - m_verlet.Add(new VRMSpringBoneLogic(center, parent, - new Vector3( - localPosition.x * scale.x, - localPosition.y * scale.y, - localPosition.z * scale.z - ))) - ; - - foreach (Transform child in parent) SetupRecursive(center, child); - } - void LateUpdate() { if (m_updateType == SpringBoneUpdateType.LateUpdate) { - UpdateProcess(Time.deltaTime); + m_system.UpdateProcess(Time.deltaTime, Scene, Settings); } } @@ -256,7 +68,7 @@ namespace VRM { if (m_updateType == SpringBoneUpdateType.FixedUpdate) { - UpdateProcess(Time.fixedDeltaTime); + m_system.UpdateProcess(Time.fixedDeltaTime, Scene, Settings); } } @@ -266,96 +78,14 @@ namespace VRM { throw new System.ArgumentException("require SpringBoneUpdateType.Manual"); } - UpdateProcess(deltaTime); - } - - public struct SphereCollider - { - // public Transform Transform; - public readonly Vector3 Position; - public readonly float Radius; - - public SphereCollider(Transform transform, VRMSpringBoneColliderGroup.SphereCollider collider) - { - Position = transform.TransformPoint(collider.Offset); - var ls = transform.lossyScale; - var scale = Mathf.Max(Mathf.Max(ls.x, ls.y), ls.z); - Radius = scale * collider.Radius; - } - } - - private List m_colliders = new List(); - private void UpdateProcess(float deltaTime) - { - if (m_verlet == null || m_verlet.Count == 0) - { - if (RootBones == null) return; - - Setup(); - } - - m_colliders.Clear(); - if (ColliderGroups != null) - { - foreach (var group in ColliderGroups) - { - if (group != null) - { - foreach (var collider in group.Colliders) - { - m_colliders.Add(new SphereCollider(group.transform, collider)); - } - } - } - } - - var stiffness = m_stiffnessForce * deltaTime; - var external = m_gravityDir * (m_gravityPower * deltaTime); - - foreach (var verlet in m_verlet) - { - verlet.SetRadius(m_hitRadius); - verlet.Update(m_center, - stiffness, - m_dragForce, - external, - m_colliders - ); - } - } - - void EditorGizmo(Transform head) - { - Vector3 childPosition; - Vector3 scale; - if (head.childCount == 0) - { - // 子ノードが無い。7cm 固定 - var delta = head.position - head.parent.position; - childPosition = head.position + delta.normalized * 0.07f * head.UniformedLossyScale(); - scale = head.lossyScale; - } - else - { - var firstChild = GetChildren(head).First(); - childPosition = firstChild.position; - scale = firstChild.lossyScale; - } - - Gizmos.DrawLine(head.position, childPosition); - Gizmos.DrawWireSphere(childPosition, m_hitRadius * scale.x); - - foreach (Transform child in head) EditorGizmo(child); + m_system.UpdateProcess(deltaTime, Scene, Settings); } private void OnDrawGizmosSelected() { if (Application.isPlaying) { - foreach (var verlet in m_verlet) - { - verlet.DrawGizmo(m_center, m_gizmoColor); - } + m_system.PlayingGizmo(m_center, m_gizmoColor); } else { @@ -365,7 +95,7 @@ namespace VRM { if (root != null) { - EditorGizmo(root.transform); + m_system.EditorGizmo(root.transform, m_hitRadius); } } } diff --git a/Assets/VRM/Samples~/FirstPersonSample/VRMRuntimeLoader.cs b/Assets/VRM/Samples~/FirstPersonSample/VRMRuntimeLoader.cs index 3e19933bc..8ca9f94e0 100644 --- a/Assets/VRM/Samples~/FirstPersonSample/VRMRuntimeLoader.cs +++ b/Assets/VRM/Samples~/FirstPersonSample/VRMRuntimeLoader.cs @@ -3,7 +3,6 @@ using System.IO; using UniGLTF; using UnityEngine; - namespace VRM.FirstPersonSample { public class VRMRuntimeLoader : MonoBehaviour @@ -114,7 +113,7 @@ namespace VRM.FirstPersonSample var loaded = default(RuntimeGltfInstance); if (m_loadAsync) { - loaded = await context.LoadAsync(new VRMShaders.RuntimeOnlyAwaitCaller()); + loaded = await context.LoadAsync(new RuntimeOnlyAwaitCaller()); } else { diff --git a/Assets/VRM/Samples~/RuntimeExporterSample/VRMRuntimeExporter.cs b/Assets/VRM/Samples~/RuntimeExporterSample/VRMRuntimeExporter.cs index 7eaf769bc..5744a3b55 100644 --- a/Assets/VRM/Samples~/RuntimeExporterSample/VRMRuntimeExporter.cs +++ b/Assets/VRM/Samples~/RuntimeExporterSample/VRMRuntimeExporter.cs @@ -1,7 +1,6 @@ using System.IO; +using UniGLTF; using UnityEngine; -using VRMShaders; - namespace VRM.RuntimeExporterSample { diff --git a/Assets/VRM/Samples~/SimpleViewer/ViewerUI.cs b/Assets/VRM/Samples~/SimpleViewer/ViewerUI.cs index d227bf369..1093736e7 100644 --- a/Assets/VRM/Samples~/SimpleViewer/ViewerUI.cs +++ b/Assets/VRM/Samples~/SimpleViewer/ViewerUI.cs @@ -7,8 +7,6 @@ using UniGLTF; using UniHumanoid; using UnityEngine; using UnityEngine.UI; -using VRMShaders; - namespace VRM.SimpleViewer { diff --git a/Assets/VRM/Tests/SampleTests/VRMImportExportTests.cs b/Assets/VRM/Tests/SampleTests/VRMImportExportTests.cs index 9cf0e3591..d0ce6b581 100644 --- a/Assets/VRM/Tests/SampleTests/VRMImportExportTests.cs +++ b/Assets/VRM/Tests/SampleTests/VRMImportExportTests.cs @@ -33,9 +33,11 @@ namespace VRM.Samples public void ImportExportTest() { var path = AliciaPath; - using (var data = new GlbFileParser(path).Parse()) - using (var context = new VRMImporterContext(new VRMData(data))) - using (var loaded = context.Load()) + using var data = new GlbFileParser(path).Parse(); + var vrmData = new VRMData(data); + var materialGenerator = new BuiltInVrmMaterialDescriptorGenerator(vrmData.VrmExtension); + using var context = new VRMImporterContext(vrmData, materialGenerator: materialGenerator); + using var loaded = context.Load(); { loaded.ShowMeshes(); loaded.EnableUpdateWhenOffscreen(); @@ -126,9 +128,11 @@ namespace VRM.Samples public void MeshCopyTest() { var path = AliciaPath; - using (var data = new GlbFileParser(path).Parse()) - using (var context = new VRMImporterContext(new VRMData(data))) - using (var loaded = context.Load()) + using var data = new GlbFileParser(path).Parse(); + var vrmData = new VRMData(data); + var materialGenerator = new BuiltInVrmMaterialDescriptorGenerator(vrmData.VrmExtension); + using var context = new VRMImporterContext(vrmData, materialGenerator: materialGenerator); + using var loaded = context.Load(); { loaded.ShowMeshes(); loaded.EnableUpdateWhenOffscreen(); @@ -147,8 +151,10 @@ namespace VRM.Samples // Aliciaを古いデシリアライザでロードする var path = AliciaPath; - using (var data = new GlbFileParser(path).Parse()) - using (var context = new VRMImporterContext(new VRMData(data))) + using var data = new GlbFileParser(path).Parse(); + var vrmData = new VRMData(data); + var materialGenerator = new BuiltInVrmMaterialDescriptorGenerator(vrmData.VrmExtension); + using var context = new VRMImporterContext(vrmData, materialGenerator: materialGenerator); { var oldJson = context.GLTF.ToJson().ParseAsJson().ToString(" "); diff --git a/Assets/VRM/Tests/TestVrm0X.cs b/Assets/VRM/Tests/TestVrm0X.cs new file mode 100644 index 000000000..6f99e905d --- /dev/null +++ b/Assets/VRM/Tests/TestVrm0X.cs @@ -0,0 +1,32 @@ +using UniGLTF; +using UnityEngine; + +namespace VRM +{ + public static class TestVrm0X + { + public static RuntimeGltfInstance LoadBytesAsBuiltInRP(byte[] bytes) + { + return VrmUtility.LoadBytesAsync( + "", + bytes, + awaitCaller: new ImmediateCaller(), + materialGeneratorCallback: x => new BuiltInVrmMaterialDescriptorGenerator(x) + ).Result; + } + + public static RuntimeGltfInstance LoadPathAsBuiltInRP(string path) + { + return VrmUtility.LoadAsync( + path, + awaitCaller: new ImmediateCaller(), + materialGeneratorCallback: x => new BuiltInVrmMaterialDescriptorGenerator(x) + ).Result; + } + + public static byte[] ExportAsBuiltInRP(GameObject gameObject, VRMExportSettings exportSettings) + { + return VRMEditorExporter.Export(gameObject, null, exportSettings, new BuiltInVrmMaterialExporter()); + } + } +} \ No newline at end of file diff --git a/Assets/VRM/Tests/TestVrm0X.cs.meta b/Assets/VRM/Tests/TestVrm0X.cs.meta new file mode 100644 index 000000000..32d715a00 --- /dev/null +++ b/Assets/VRM/Tests/TestVrm0X.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 47b1209d83114ccbaa0bf02436b8eb04 +timeCreated: 1722265572 \ No newline at end of file diff --git a/Assets/VRM/Tests/VRMLookAtTests.cs b/Assets/VRM/Tests/VRMLookAtTests.cs index a9a07b4a3..40d9424aa 100644 --- a/Assets/VRM/Tests/VRMLookAtTests.cs +++ b/Assets/VRM/Tests/VRMLookAtTests.cs @@ -21,11 +21,8 @@ namespace VRM [Test] public void VRMLookAtTest() { - var data = new GlbFileParser(AliciaPath).Parse(); byte[] bytes = default; - using (data) - using (var loader = new VRMImporterContext(new VRMData(data))) - using (var loaded = loader.Load()) + using var loaded = TestVrm0X.LoadPathAsBuiltInRP(AliciaPath); { loaded.ShowMeshes(); @@ -35,12 +32,12 @@ namespace VRM var lookAt = go.AddComponent(); var settings = (VRMExportSettings)ScriptableObject.CreateInstance(); settings.PoseFreeze = true; - bytes = VRMEditorExporter.Export(go, null, settings); - } + bytes = TestVrm0X.ExportAsBuiltInRP(go, settings); + } - using (var data2 = new GlbLowLevelParser(AliciaPath, bytes).Parse()) - using (var loader2 = new VRMImporterContext(new VRMData(data2))) { + using var data2 = new GlbLowLevelParser(AliciaPath, bytes).Parse(); + using var loader2 = new VRMImporterContext(new VRMData(data2)); Assert.AreEqual(LookAtType.BlendShape, loader2.VRM.firstPerson.lookAtType); } } @@ -48,13 +45,10 @@ namespace VRM [Test] public void VRMLookAtCurveMapWithFreezeTest() { - var data = new GlbFileParser(AliciaPath).Parse(); - byte[] bytes = default; + byte[] bytes; CurveMapper horizontalInner = default; - using (data) - using (var loader = new VRMImporterContext(new VRMData(data))) - using (var loaded = loader.Load()) { + using var loaded = TestVrm0X.LoadPathAsBuiltInRP(AliciaPath); loaded.ShowMeshes(); var go = loaded.gameObject; @@ -63,13 +57,11 @@ namespace VRM horizontalInner = lookAt.HorizontalInner; var settings = ScriptableObject.CreateInstance(); settings.PoseFreeze = true; - bytes = VRMEditorExporter.Export(go, null, settings); + bytes = TestVrm0X.ExportAsBuiltInRP(go, settings); } - using (var data2 = new GlbLowLevelParser(AliciaPath, bytes).Parse()) - using (var loader = new VRMImporterContext(new VRMData(data2))) - using (var loaded = loader.Load()) { + using var loaded = TestVrm0X.LoadBytesAsBuiltInRP(bytes); loaded.ShowMeshes(); var lookAt = loaded.GetComponent(); @@ -81,13 +73,10 @@ namespace VRM [Test] public void VRMLookAtCurveMapTest() { - var data = new GlbFileParser(AliciaPath).Parse(); - byte[] bytes = default; + byte[] bytes; CurveMapper horizontalInner = default; - using (data) - using (var loader = new VRMImporterContext(new VRMData(data))) - using (var loaded = loader.Load()) { + using var loaded = TestVrm0X.LoadPathAsBuiltInRP(AliciaPath); loaded.ShowMeshes(); var go = loaded.gameObject; @@ -96,13 +85,11 @@ namespace VRM horizontalInner = lookAt.HorizontalInner; var settings = (VRMExportSettings)ScriptableObject.CreateInstance(); settings.PoseFreeze = false; - bytes = VRMEditorExporter.Export(go, null, settings); + bytes = TestVrm0X.ExportAsBuiltInRP(go, settings); } - using (var data2 = new GlbLowLevelParser(AliciaPath, bytes).Parse()) - using (var loader = new VRMImporterContext(new VRMData(data2))) - using (var loaded = loader.Load()) { + using var loaded = TestVrm0X.LoadBytesAsBuiltInRP(bytes); loaded.ShowMeshes(); var lookAt = loaded.GetComponent(); diff --git a/Assets/VRM/Tests/VrmDividedMeshTests.cs b/Assets/VRM/Tests/VrmDividedMeshTests.cs index 543b10486..658cda4eb 100644 --- a/Assets/VRM/Tests/VrmDividedMeshTests.cs +++ b/Assets/VRM/Tests/VrmDividedMeshTests.cs @@ -67,13 +67,21 @@ namespace VRM var path = AliciaPath; var loaded = Load(File.ReadAllBytes(path), path); - var exported = VRMExporter.Export(new UniGLTF.GltfExportSettings + var exportSettings = new GltfExportSettings { DivideVertexBuffer = true, // test this ExportOnlyBlendShapePosition = true, ExportTangents = false, UseSparseAccessorForMorphTarget = true, - }, loaded, new EditorTextureSerializer()); + }; + var exported = new ExportingGltfData(); + using var exporter = new VRMExporter( + exported, + exportSettings, + textureSerializer: new EditorTextureSerializer(), + materialExporter: new BuiltInVrmMaterialExporter()); + exporter.Prepare(loaded); + exporter.Export(); var bytes = exported.ToGlbBytes(); var divided = Load(bytes, path); diff --git a/Assets/VRM/package.json b/Assets/VRM/package.json index 4a527ae19..9740d2d5d 100644 --- a/Assets/VRM/package.json +++ b/Assets/VRM/package.json @@ -1,6 +1,6 @@ { "name": "com.vrmc.univrm", - "version": "0.124.2", + "version": "0.125.0", "displayName": "VRM", "description": "VRM importer", "unity": "2021.3", @@ -14,7 +14,7 @@ "name": "VRM Consortium" }, "dependencies": { - "com.vrmc.gltf": "0.124.2", + "com.vrmc.gltf": "0.125.0", "com.unity.ugui": "1.0.0" }, "samples": [ diff --git a/Assets/VRM10/Editor/Components/SpringBone/VRM10SpringBoneColliderEditor.cs b/Assets/VRM10/Editor/Components/SpringBone/VRM10SpringBoneColliderEditor.cs index 7680d87de..06bc6ded3 100644 --- a/Assets/VRM10/Editor/Components/SpringBone/VRM10SpringBoneColliderEditor.cs +++ b/Assets/VRM10/Editor/Components/SpringBone/VRM10SpringBoneColliderEditor.cs @@ -6,6 +6,18 @@ namespace UniVRM10 [CustomEditor(typeof(VRM10SpringBoneCollider))] class VRM10SpringBoneColliderEditor : Editor { + VRM10SpringBoneCollider _target; + Vrm10Instance _vrm; + + private void OnEnable() + { + _target = (VRM10SpringBoneCollider)target; + if(_target!=null) + { + _vrm = _target.GetComponentInParent(); + } + } + public override void OnInspectorGUI() { if (VRM10Window.Active == target) @@ -41,7 +53,18 @@ namespace UniVRM10 DrawPropertiesExcluding(serializedObject, nameof(component.Normal), "m_Script"); break; } - serializedObject.ApplyModifiedProperties(); + + if (serializedObject.ApplyModifiedProperties()) + { + if (Application.isPlaying) + { + // UniGLTF.UniGLTFLogger.Log("invaliate"); + if(_vrm!=null) + { + _vrm.Runtime.SpringBone.ReconstructSpringBone(); + } + } + } } } } \ No newline at end of file diff --git a/Assets/VRM10/Editor/Components/SpringBone/VRM10SpringBoneJointEditor.cs b/Assets/VRM10/Editor/Components/SpringBone/VRM10SpringBoneJointEditor.cs index a298088ef..7e5ef5aba 100644 --- a/Assets/VRM10/Editor/Components/SpringBone/VRM10SpringBoneJointEditor.cs +++ b/Assets/VRM10/Editor/Components/SpringBone/VRM10SpringBoneJointEditor.cs @@ -70,7 +70,17 @@ namespace UniVRM10 LimitBreakSlider(m_jointRadiusProp, 0.0f, 0.5f, 0.0f, Mathf.Infinity); } - serializedObject.ApplyModifiedProperties(); + if (serializedObject.ApplyModifiedProperties()) + { + if (Application.isPlaying) + { + // UniGLTF.UniGLTFLogger.Log("invaliate"); + if(m_root!=null) + { + m_root.Runtime.SpringBone.ReconstructSpringBone(); + } + } + } } /// diff --git a/Assets/VRM10/Editor/ScriptedImporter/VrmScriptedImporter.cs b/Assets/VRM10/Editor/ScriptedImporter/VrmScriptedImporter.cs index be82aec15..2981e8ead 100644 --- a/Assets/VRM10/Editor/ScriptedImporter/VrmScriptedImporter.cs +++ b/Assets/VRM10/Editor/ScriptedImporter/VrmScriptedImporter.cs @@ -1,4 +1,5 @@ -using UnityEngine; +using UniGLTF; +using UnityEngine; #if UNITY_2020_2_OR_NEWER using UnityEditor.AssetImporters; #else @@ -15,23 +16,11 @@ namespace UniVRM10 public bool MigrateToVrm1 = default; [SerializeField] - public UniGLTF.RenderPipelineTypes RenderPipeline = default; + public ImporterRenderPipelineTypes RenderPipeline = default; public override void OnImportAsset(AssetImportContext ctx) { VrmScriptedImporterImpl.Import(this, ctx, MigrateToVrm1, RenderPipeline); } - - void OnValidate() - { - if (RenderPipeline == UniGLTF.RenderPipelineTypes.UniversalRenderPipeline) - { - if (Shader.Find(UniGLTF.UrpGltfPbrMaterialImporter.ShaderName) == null) - { - Debug.LogWarning("URP is not installed. Force to BuiltinRenderPipeline"); - RenderPipeline = UniGLTF.RenderPipelineTypes.BuiltinRenderPipeline; - } - } - } } } diff --git a/Assets/VRM10/Editor/ScriptedImporter/VrmScriptedImporterImpl.cs b/Assets/VRM10/Editor/ScriptedImporter/VrmScriptedImporterImpl.cs index 32ef5d600..c748a9451 100644 --- a/Assets/VRM10/Editor/ScriptedImporter/VrmScriptedImporterImpl.cs +++ b/Assets/VRM10/Editor/ScriptedImporter/VrmScriptedImporterImpl.cs @@ -15,23 +15,29 @@ namespace UniVRM10 { public static class VrmScriptedImporterImpl { - static IMaterialDescriptorGenerator GetMaterialDescriptorGenerator(RenderPipelineTypes renderPipeline) + /// + /// Vrm-1.0 の Asset にアイコンを付与する + /// + static Texture2D _AssetIcon = null; + static Texture2D AssetIcon { - var settings = Vrm10ProjectEditorSettings.instance; - if (settings.MaterialDescriptorGeneratorFactory != null) + get { - return settings.MaterialDescriptorGeneratorFactory.Create(); + if (_AssetIcon == null) + { + // try package + _AssetIcon = UnityEditor.AssetDatabase.LoadAssetAtPath("Packages/com.vrmc.vrm/Icons/vrm-48x48.png"); + } + if (_AssetIcon == null) + { + // try assets + _AssetIcon = UnityEditor.AssetDatabase.LoadAssetAtPath("Assets/VRM10/Icons/vrm-48x48.png"); + } + return _AssetIcon; } - - return renderPipeline switch - { - RenderPipelineTypes.BuiltinRenderPipeline => new BuiltInVrm10MaterialDescriptorGenerator(), - RenderPipelineTypes.UniversalRenderPipeline => new UrpVrm10MaterialDescriptorGenerator(), - _ => throw new NotImplementedException() - }; } - static void Process(Vrm10Data result, ScriptedImporter scriptedImporter, AssetImportContext context, RenderPipelineTypes renderPipeline) + static void Process(Vrm10Data result, ScriptedImporter scriptedImporter, AssetImportContext context, ImporterRenderPipelineTypes renderPipeline) { // // Import(create unity objects) @@ -60,7 +66,7 @@ namespace UniVRM10 var root = loaded.Root; GameObject.DestroyImmediate(loaded); - context.AddObjectToAsset(root.name, root); + context.AddObjectToAsset(root.name, root, AssetIcon); context.SetMainObject(root); } } @@ -73,7 +79,7 @@ namespace UniVRM10 /// vrm0 だった場合に vrm1 化する /// /// normalize する - public static void Import(ScriptedImporter scriptedImporter, AssetImportContext context, bool doMigrate, RenderPipelineTypes renderPipeline) + public static void Import(ScriptedImporter scriptedImporter, AssetImportContext context, bool doMigrate, ImporterRenderPipelineTypes renderPipeline) { if (Symbols.VRM_DEVELOP) { @@ -113,5 +119,22 @@ namespace UniVRM10 return; } } + + private static IMaterialDescriptorGenerator GetMaterialDescriptorGenerator(ImporterRenderPipelineTypes renderPipeline) + { + var settings = Vrm10ProjectEditorSettings.instance; + if (settings.MaterialDescriptorGeneratorFactory != null) + { + return settings.MaterialDescriptorGeneratorFactory.Create(); + } + + return renderPipeline switch + { + ImporterRenderPipelineTypes.Auto => Vrm10MaterialDescriptorGeneratorUtility.GetValidVrm10MaterialDescriptorGenerator(), + ImporterRenderPipelineTypes.BuiltinRenderPipeline => Vrm10MaterialDescriptorGeneratorUtility.GetVrm10MaterialDescriptorGenerator(RenderPipelineTypes.BuiltinRenderPipeline), + ImporterRenderPipelineTypes.UniversalRenderPipeline => Vrm10MaterialDescriptorGeneratorUtility.GetVrm10MaterialDescriptorGenerator(RenderPipelineTypes.UniversalRenderPipeline), + _ => Vrm10MaterialDescriptorGeneratorUtility.GetValidVrm10MaterialDescriptorGenerator(), + }; + } } } \ No newline at end of file diff --git a/Assets/VRM10/Icons.meta b/Assets/VRM10/Icons.meta new file mode 100644 index 000000000..766b770a4 --- /dev/null +++ b/Assets/VRM10/Icons.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 82c4e6eb721c7594e8d30a49b2ecbbab +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/VRM10/Icons/vrm-48x48.png b/Assets/VRM10/Icons/vrm-48x48.png new file mode 100644 index 000000000..2a805c6b0 Binary files /dev/null and b/Assets/VRM10/Icons/vrm-48x48.png differ diff --git a/Assets/VRM10/Icons/vrm-48x48.png.meta b/Assets/VRM10/Icons/vrm-48x48.png.meta new file mode 100644 index 000000000..5203aa2e5 --- /dev/null +++ b/Assets/VRM10/Icons/vrm-48x48.png.meta @@ -0,0 +1,123 @@ +fileFormatVersion: 2 +guid: ad4861e134018c948ac79793d290f48b +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 12 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMasterTextureLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 1 + aniso: 1 + mipBias: 0 + wrapU: 0 + wrapV: 0 + wrapW: 0 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + cookieLightType: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Server + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + nameFileIdTable: {} + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone .cs b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone.cs similarity index 99% rename from Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone .cs rename to Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone.cs index e0b37334f..335f0c986 100644 --- a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone .cs +++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone.cs @@ -64,7 +64,7 @@ namespace UniVRM10 /// public void ReconstructSpringBone() { - // rerelase + // release if (m_fastSpringBoneBuffer != null) { m_fastSpringBoneService.BufferCombiner.Unregister(m_fastSpringBoneBuffer); diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone .cs.meta b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone.cs.meta similarity index 100% rename from Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone .cs.meta rename to Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeSpringBone.cs.meta diff --git a/Assets/VRM10/Runtime/Components/VrmAnimationInstance/Vrm10AnimationInstance.cs b/Assets/VRM10/Runtime/Components/VrmAnimationInstance/Vrm10AnimationInstance.cs index 39bce21b7..2835f6ab6 100644 --- a/Assets/VRM10/Runtime/Components/VrmAnimationInstance/Vrm10AnimationInstance.cs +++ b/Assets/VRM10/Runtime/Components/VrmAnimationInstance/Vrm10AnimationInstance.cs @@ -171,7 +171,7 @@ namespace UniVRM10 public float custom_98; public float custom_99; - public void Initialize(IEnumerable keys) + public void Initialize(IEnumerable keys, Material material) { var humanoid = gameObject.AddComponent(); if (humanoid.AssignBonesFromAnimator()) @@ -183,7 +183,6 @@ namespace UniVRM10 // create SkinnedMesh for bone visualize var animator = this.GetComponentOrThrow(); BoxMan = SkeletonMeshUtility.CreateRenderer(animator); - var material = new Material(Shader.Find("Standard")); BoxMan.sharedMaterial = material; var mesh = BoxMan.sharedMesh; mesh.name = "box-man"; diff --git a/Assets/VRM10/Runtime/IO/Material/BuiltInRP/Import/BuiltInVrm10MaterialDescriptorGenerator.cs b/Assets/VRM10/Runtime/IO/Material/BuiltInRP/Import/BuiltInVrm10MaterialDescriptorGenerator.cs index ec6b09115..15d27c2e6 100644 --- a/Assets/VRM10/Runtime/IO/Material/BuiltInRP/Import/BuiltInVrm10MaterialDescriptorGenerator.cs +++ b/Assets/VRM10/Runtime/IO/Material/BuiltInRP/Import/BuiltInVrm10MaterialDescriptorGenerator.cs @@ -21,20 +21,9 @@ namespace UniVRM10 { Debug.LogWarning($"material: {i} out of range. fallback"); } - return new MaterialDescriptor( - GltfMaterialImportUtils.ImportMaterialName(i, null), - BuiltInGltfPbrMaterialImporter.Shader, - null, - new Dictionary(), - new Dictionary(), - new Dictionary(), - new Dictionary(), - new Action[]{}); + return GetGltfDefault(GltfMaterialImportUtils.ImportMaterialName(i, null)); } - public MaterialDescriptor GetGltfDefault() - { - return BuiltInGltfDefaultMaterialImporter.CreateParam(); - } + public MaterialDescriptor GetGltfDefault(string materialName = null) => BuiltInGltfDefaultMaterialImporter.CreateParam(materialName); } } diff --git a/Assets/VRM10/Runtime/IO/Material/URP/Export.meta b/Assets/VRM10/Runtime/IO/Material/URP/Export.meta new file mode 100644 index 000000000..110719821 --- /dev/null +++ b/Assets/VRM10/Runtime/IO/Material/URP/Export.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a6506c50290f7fb48984c1c5e83929e4 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/VRM10/Runtime/IO/Material/URP/Export/UrpVrm10MaterialExporter.cs b/Assets/VRM10/Runtime/IO/Material/URP/Export/UrpVrm10MaterialExporter.cs new file mode 100644 index 000000000..f4795e313 --- /dev/null +++ b/Assets/VRM10/Runtime/IO/Material/URP/Export/UrpVrm10MaterialExporter.cs @@ -0,0 +1,19 @@ +using UniGLTF; +using UnityEngine; + +namespace UniVRM10 +{ + public class UrpVrm10MaterialExporter : IMaterialExporter + { + public glTFMaterial ExportMaterial(Material m, ITextureExporter textureExporter, GltfExportSettings settings) + { + #if UNITY_EDITOR + return new glTFMaterial{ + name = "dummyForTest", + }; + #else + throw new System.NotImplementedException(); + #endif + } + } +} diff --git a/Assets/VRM10/Runtime/IO/Material/URP/Export/UrpVrm10MaterialExporter.cs.meta b/Assets/VRM10/Runtime/IO/Material/URP/Export/UrpVrm10MaterialExporter.cs.meta new file mode 100644 index 000000000..1678788b4 --- /dev/null +++ b/Assets/VRM10/Runtime/IO/Material/URP/Export/UrpVrm10MaterialExporter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 95b7c97505db9d747b04136aa1505204 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/VRM10/Runtime/IO/Material/URP/Import/UrpVrm10MaterialDescriptorGenerator.cs b/Assets/VRM10/Runtime/IO/Material/URP/Import/UrpVrm10MaterialDescriptorGenerator.cs index b0cf9d20b..f3ae462a2 100644 --- a/Assets/VRM10/Runtime/IO/Material/URP/Import/UrpVrm10MaterialDescriptorGenerator.cs +++ b/Assets/VRM10/Runtime/IO/Material/URP/Import/UrpVrm10MaterialDescriptorGenerator.cs @@ -7,6 +7,9 @@ namespace UniVRM10 { public sealed class UrpVrm10MaterialDescriptorGenerator : IMaterialDescriptorGenerator { + public UrpGltfPbrMaterialImporter PbrMaterialImporter { get; } = new(); + public UrpGltfDefaultMaterialImporter DefaultMaterialImporter { get; } = new(); + public MaterialDescriptor Get(GltfData data, int i) { // mtoon @@ -14,24 +17,16 @@ namespace UniVRM10 // unlit if (BuiltInGltfUnlitMaterialImporter.TryCreateParam(data, i, out matDesc)) return matDesc; // pbr - if (UrpGltfPbrMaterialImporter.TryCreateParam(data, i, out matDesc)) return matDesc; + if (PbrMaterialImporter.TryCreateParam(data, i, out matDesc)) return matDesc; - // fallback - Debug.LogWarning($"material: {i} out of range. fallback"); - return new MaterialDescriptor( - GltfMaterialImportUtils.ImportMaterialName(i, null), - UrpGltfPbrMaterialImporter.Shader, - null, - new Dictionary(), - new Dictionary(), - new Dictionary(), - new Dictionary(), - new Action[]{}); + // NOTE: Fallback to default material + if (Symbols.VRM_DEVELOP) + { + Debug.LogWarning($"material: {i} out of range. fallback"); + } + return GetGltfDefault(GltfMaterialImportUtils.ImportMaterialName(i, null)); } - public MaterialDescriptor GetGltfDefault() - { - return UrpGltfDefaultMaterialImporter.CreateParam(); - } + public MaterialDescriptor GetGltfDefault(string materialName = null) => DefaultMaterialImporter.CreateParam(materialName); } } diff --git a/Assets/VRM10/Runtime/IO/Material/Vrm10MaterialDescriptorGeneratorUtility.cs b/Assets/VRM10/Runtime/IO/Material/Vrm10MaterialDescriptorGeneratorUtility.cs index d45c4741d..3dcdc745c 100644 --- a/Assets/VRM10/Runtime/IO/Material/Vrm10MaterialDescriptorGeneratorUtility.cs +++ b/Assets/VRM10/Runtime/IO/Material/Vrm10MaterialDescriptorGeneratorUtility.cs @@ -6,7 +6,12 @@ namespace UniVRM10 { public static IMaterialDescriptorGenerator GetValidVrm10MaterialDescriptorGenerator() { - return RenderPipelineUtility.GetRenderPipelineType() switch + return GetVrm10MaterialDescriptorGenerator(RenderPipelineUtility.GetRenderPipelineType()); + } + + public static IMaterialDescriptorGenerator GetVrm10MaterialDescriptorGenerator(RenderPipelineTypes renderPipelineType) + { + return renderPipelineType switch { RenderPipelineTypes.UniversalRenderPipeline => new UrpVrm10MaterialDescriptorGenerator(), RenderPipelineTypes.BuiltinRenderPipeline => new BuiltInVrm10MaterialDescriptorGenerator(), diff --git a/Assets/VRM10/Runtime/IO/Material/Vrm10MaterialExporterUtility.cs b/Assets/VRM10/Runtime/IO/Material/Vrm10MaterialExporterUtility.cs index 5f8e61397..2ba387126 100644 --- a/Assets/VRM10/Runtime/IO/Material/Vrm10MaterialExporterUtility.cs +++ b/Assets/VRM10/Runtime/IO/Material/Vrm10MaterialExporterUtility.cs @@ -8,7 +8,7 @@ namespace UniVRM10 { return RenderPipelineUtility.GetRenderPipelineType() switch { - RenderPipelineTypes.UniversalRenderPipeline => throw new System.NotImplementedException(), + RenderPipelineTypes.UniversalRenderPipeline => new UrpVrm10MaterialExporter(), RenderPipelineTypes.BuiltinRenderPipeline => new BuiltInVrm10MaterialExporter(), _ => new BuiltInVrm10MaterialExporter(), }; diff --git a/Assets/VRM10/Runtime/IO/Vrm10.cs b/Assets/VRM10/Runtime/IO/Vrm10.cs index 7532f88e3..1f3661ea8 100644 --- a/Assets/VRM10/Runtime/IO/Vrm10.cs +++ b/Assets/VRM10/Runtime/IO/Vrm10.cs @@ -34,6 +34,7 @@ namespace UniVRM10 /// this loader use specified material generation strategy. /// return callback that notify meta information before loading. /// CancellationToken + /// Importer context settings. /// vrm-1.0 instance. Maybe return null if unexpected error was raised. public static async Task LoadPathAsync( string path, @@ -44,7 +45,8 @@ namespace UniVRM10 ITextureDeserializer textureDeserializer = null, IMaterialDescriptorGenerator materialGenerator = null, VrmMetaInformationCallback vrmMetaInformationCallback = null, - CancellationToken ct = default) + CancellationToken ct = default, + ImporterContextSettings importerContextSettings = null) { awaitCaller ??= Application.isPlaying ? new RuntimeOnlyAwaitCaller() @@ -64,7 +66,8 @@ namespace UniVRM10 textureDeserializer, materialGenerator, vrmMetaInformationCallback, - ct); + ct, + importerContextSettings); } /// @@ -82,6 +85,7 @@ namespace UniVRM10 /// this loader use specified material generation strategy. /// return callback that notify meta information before loading. /// CancellationToken + /// Importer context settings. /// vrm-1.0 instance. Maybe return null if unexpected error was raised. public static async Task LoadBytesAsync( byte[] bytes, @@ -92,7 +96,8 @@ namespace UniVRM10 ITextureDeserializer textureDeserializer = null, IMaterialDescriptorGenerator materialGenerator = null, VrmMetaInformationCallback vrmMetaInformationCallback = null, - CancellationToken ct = default) + CancellationToken ct = default, + ImporterContextSettings importerContextSettings = null) { awaitCaller ??= Application.isPlaying ? new RuntimeOnlyAwaitCaller() @@ -108,7 +113,8 @@ namespace UniVRM10 textureDeserializer, materialGenerator, vrmMetaInformationCallback, - ct); + ct, + importerContextSettings); } /// @@ -127,6 +133,7 @@ namespace UniVRM10 /// this loader use specified material generation strategy. /// return callback that notify meta information before loading. /// CancellationToken + /// Importer context settings. /// vrm-1.0 instance. Maybe return null if unexpected error was raised. public static async Task LoadGltfDataAsync( GltfData gltfData, @@ -137,7 +144,8 @@ namespace UniVRM10 ITextureDeserializer textureDeserializer = null, IMaterialDescriptorGenerator materialGenerator = null, VrmMetaInformationCallback vrmMetaInformationCallback = null, - CancellationToken ct = default) + CancellationToken ct = default, + ImporterContextSettings importerContextSettings = null) { awaitCaller ??= Application.isPlaying ? new RuntimeOnlyAwaitCaller() @@ -152,7 +160,8 @@ namespace UniVRM10 textureDeserializer, materialGenerator, vrmMetaInformationCallback, - ct); + ct, + importerContextSettings); } private static async Task LoadAsync( @@ -164,7 +173,8 @@ namespace UniVRM10 ITextureDeserializer textureDeserializer, IMaterialDescriptorGenerator materialGenerator, VrmMetaInformationCallback vrmMetaInformationCallback, - CancellationToken ct) + CancellationToken ct, + ImporterContextSettings importerContextSettings = null) { ct.ThrowIfCancellationRequested(); if (awaitCaller == null) @@ -181,7 +191,8 @@ namespace UniVRM10 textureDeserializer, materialGenerator, vrmMetaInformationCallback, - ct); + ct, + importerContextSettings); if (instance != null) { if (ct.IsCancellationRequested) @@ -230,7 +241,8 @@ namespace UniVRM10 ITextureDeserializer textureDeserializer, IMaterialDescriptorGenerator materialGenerator, VrmMetaInformationCallback vrmMetaInformationCallback, - CancellationToken ct) + CancellationToken ct, + ImporterContextSettings importerContextSettings = null) { ct.ThrowIfCancellationRequested(); if (awaitCaller == null) @@ -256,7 +268,8 @@ namespace UniVRM10 textureDeserializer, materialGenerator, vrmMetaInformationCallback, - ct); + ct, + importerContextSettings); } private static async Task TryMigratingFromVrm0XAsync( @@ -313,7 +326,8 @@ namespace UniVRM10 ITextureDeserializer textureDeserializer, IMaterialDescriptorGenerator materialGenerator, VrmMetaInformationCallback vrmMetaInformationCallback, - CancellationToken ct) + CancellationToken ct, + ImporterContextSettings importerContextSettings = null) { ct.ThrowIfCancellationRequested(); if (awaitCaller == null) @@ -330,7 +344,8 @@ namespace UniVRM10 vrm10Data, textureDeserializer: textureDeserializer, materialGenerator: materialGenerator, - useControlRig: controlRigGenerationOption != ControlRigGenerationOption.None)) + useControlRig: controlRigGenerationOption != ControlRigGenerationOption.None, + settings: importerContextSettings)) { // 1. Load meta information if callback was available. if (vrmMetaInformationCallback != null) diff --git a/Assets/VRM10/Runtime/IO/Vrm10Exporter.cs b/Assets/VRM10/Runtime/IO/Vrm10Exporter.cs index 864c1e6ff..efa2ecfbb 100644 --- a/Assets/VRM10/Runtime/IO/Vrm10Exporter.cs +++ b/Assets/VRM10/Runtime/IO/Vrm10Exporter.cs @@ -11,6 +11,7 @@ namespace UniVRM10 { public const string VRM_SPEC_VERSION = "1.0"; public const string SPRINGBONE_SPEC_VERSION = "1.0"; + public const string SPRINGBONE_EXTENDED_COLLIDER_SPEC_VERSION = "1.0"; public const string NODE_CONSTRAINT_SPEC_VERSION = "1.0"; public const string MTOON_SPEC_VERSION = "1.0"; @@ -500,6 +501,7 @@ namespace UniVRM10 { var extendedCollider = new UniGLTF.Extensions.VRMC_springBone_extended_collider.VRMC_springBone_extended_collider { + SpecVersion = SPRINGBONE_EXTENDED_COLLIDER_SPEC_VERSION, Shape = ExportShapeExtended(c), }; glTFExtension extensions = default; diff --git a/Assets/VRM10/Runtime/IO/Vrm10Importer.cs b/Assets/VRM10/Runtime/IO/Vrm10Importer.cs index a9447fea7..31d49fc5d 100644 --- a/Assets/VRM10/Runtime/IO/Vrm10Importer.cs +++ b/Assets/VRM10/Runtime/IO/Vrm10Importer.cs @@ -29,9 +29,10 @@ namespace UniVRM10 IReadOnlyDictionary externalObjectMap = null, ITextureDeserializer textureDeserializer = null, IMaterialDescriptorGenerator materialGenerator = null, - bool useControlRig = false + bool useControlRig = false, + ImporterContextSettings settings = null ) - : base(vrm.Data, externalObjectMap, textureDeserializer) + : base(vrm.Data, externalObjectMap, textureDeserializer, settings: settings) { if (vrm == null) { diff --git a/Assets/VRM10/Runtime/IO/VrmAnimationImporter.cs b/Assets/VRM10/Runtime/IO/VrmAnimationImporter.cs index 933a3727e..41674c19e 100644 --- a/Assets/VRM10/Runtime/IO/VrmAnimationImporter.cs +++ b/Assets/VRM10/Runtime/IO/VrmAnimationImporter.cs @@ -18,10 +18,8 @@ namespace UniVRM10 IReadOnlyDictionary externalObjectMap = null, ITextureDeserializer textureDeserializer = null, IMaterialDescriptorGenerator materialGenerator = null) - : base(data, externalObjectMap, textureDeserializer, materialGenerator) + : base(data, externalObjectMap, textureDeserializer, materialGenerator, new ImporterContextSettings(invertAxis: Axes.X)) { - InvertAxis = Axes.X; - m_vrma = GetExtension(Data); } @@ -244,6 +242,9 @@ namespace UniVRM10 } Data.GLTF.scenes[0].nodes = Data.GLTF.scenes[0].nodes.Take(1).ToArray(); + // 可視化メッシュ用マテリアル。base.LoadAsync を呼ぶ前に生成する。 + var defaultMaterial = await MaterialFactory.GetDefaultMaterialAsync(awaitCaller); + // Humanoid Animation が Gltf アニメーションとしてロードされる var instance = await base.LoadAsync(awaitCaller, measureTime); @@ -285,7 +286,7 @@ namespace UniVRM10 // VRMA-animation solver var animationInstance = instance.gameObject.AddComponent(); - animationInstance.Initialize(expressions.Select(x => x.Key)); + animationInstance.Initialize(expressions.Select(x => x.Key), defaultMaterial); return instance; } diff --git a/Assets/VRM10/Samples~/SimpleVrma/SimpleVrma.cs b/Assets/VRM10/Samples~/SimpleVrma/SimpleVrma.cs index 5db457913..cc8c2f25b 100644 --- a/Assets/VRM10/Samples~/SimpleVrma/SimpleVrma.cs +++ b/Assets/VRM10/Samples~/SimpleVrma/SimpleVrma.cs @@ -1,8 +1,7 @@ using UniGLTF; using UnityEngine; using UniVRM10; -using UniVRM10.VRM10Viewer; -using VRMShaders; + #if UNITY_EDITOR using UnityEditor; #endif @@ -47,7 +46,7 @@ public class SimpleVrma : MonoBehaviour showMeshes: false, awaitCaller: new ImmediateCaller()); - var instance = Vrm.GetComponentOrThrow(); + var instance = Vrm.GetComponent(); instance.ShowMeshes(); } @@ -58,11 +57,11 @@ public class SimpleVrma : MonoBehaviour using var loader = new VrmAnimationImporter(data); var instance = await loader.LoadAsync(new ImmediateCaller()); - Vrma = instance.GetComponentOrThrow(); + Vrma = instance.GetComponent(); Vrm.Runtime.VrmAnimation = Vrma; Debug.Log(Vrma); - var animation = Vrma.GetComponentOrThrow(); + var animation = Vrma.GetComponent(); animation.Play(); } } diff --git a/Assets/VRM10/Samples~/URPSample/Runtime/UrpSampleUI.cs b/Assets/VRM10/Samples~/URPSample/Runtime/UrpSampleUI.cs index 47d7a08f3..b952b4786 100644 --- a/Assets/VRM10/Samples~/URPSample/Runtime/UrpSampleUI.cs +++ b/Assets/VRM10/Samples~/URPSample/Runtime/UrpSampleUI.cs @@ -46,7 +46,7 @@ namespace UniVRM10.URPSample return; } - var instance = _loadedVrm.GetComponentOrThrow(); + var instance = _loadedVrm.GetComponent(); instance.ShowMeshes(); instance.EnableUpdateWhenOffscreen(); diff --git a/Assets/VRM10/Samples~/VRM10FirstPersonSample/VRM10RuntimeLoader.cs b/Assets/VRM10/Samples~/VRM10FirstPersonSample/VRM10RuntimeLoader.cs index 2ecba4ef7..d0b498891 100644 --- a/Assets/VRM10/Samples~/VRM10FirstPersonSample/VRM10RuntimeLoader.cs +++ b/Assets/VRM10/Samples~/VRM10FirstPersonSample/VRM10RuntimeLoader.cs @@ -33,7 +33,8 @@ namespace UniVRM10.FirstPersonSample m_target.Source = m_source; m_target.SourceType = UniHumanoid.HumanPoseTransfer.HumanPoseTransferSourceType.HumanPoseTransfer; - if (m_target.TryGetComponent(out var animator)) + var animator = m_target.GetComponent(); + if (animator != null) { if (m_faceCamera != null) { @@ -68,7 +69,7 @@ namespace UniVRM10.FirstPersonSample return; } - var instance = await LoadAsync(path, new VRMShaders.RuntimeOnlyAwaitCaller()); + var instance = await LoadAsync(path, new RuntimeOnlyAwaitCaller()); var root = instance.gameObject; root.transform.SetParent(transform, false); @@ -83,14 +84,14 @@ namespace UniVRM10.FirstPersonSample SetupTarget(m_target); } - async Task LoadAsync(string path, VRMShaders.IAwaitCaller awaitCaller) + async Task LoadAsync(string path, IAwaitCaller awaitCaller) { var instance = await Vrm10.LoadPathAsync(path, awaitCaller: awaitCaller, showMeshes: false); // VR用 FirstPerson 設定 await instance.Vrm.FirstPerson.SetupAsync(instance.gameObject, awaitCaller); - instance.GetComponentOrThrow().ShowMeshes(); + instance.GetComponent().ShowMeshes(); return instance; } @@ -126,7 +127,7 @@ namespace UniVRM10.FirstPersonSample { GameObject.Destroy(m_source.gameObject); } - m_source = context.Root.GetComponentOrThrow(); + m_source = context.Root.GetComponent(); SetupTarget(m_target); } diff --git a/Assets/VRM10/Samples~/VRM10RuntimeExporterSample/VRM10RuntimeExporter.cs b/Assets/VRM10/Samples~/VRM10RuntimeExporterSample/VRM10RuntimeExporter.cs index b99ce3bf9..f76da8c6b 100644 --- a/Assets/VRM10/Samples~/VRM10RuntimeExporterSample/VRM10RuntimeExporter.cs +++ b/Assets/VRM10/Samples~/VRM10RuntimeExporterSample/VRM10RuntimeExporter.cs @@ -1,7 +1,6 @@ using System.IO; using UniGLTF; using UnityEngine; -using VRMShaders; namespace UniVRM10.RuntimeExporterSample { @@ -47,7 +46,7 @@ namespace UniVRM10.RuntimeExporterSample } var vrm10 = await Vrm10.LoadPathAsync(path); - var loaded = vrm10.GetComponentOrThrow(); + var loaded = vrm10.GetComponent(); loaded.ShowMeshes(); loaded.EnableUpdateWhenOffscreen(); @@ -143,10 +142,7 @@ namespace UniVRM10.RuntimeExporterSample model.ConvertCoordinate(VrmLib.Coordinates.Vrm1, ignoreVrm: false); // export vrm-1.0 - var exporter = new UniVRM10.Vrm10Exporter(new RuntimeTextureSerializer(), new GltfExportSettings - { - - }); + var exporter = new Vrm10Exporter(new GltfExportSettings()); exporter.Export(root, model, converter, new VrmLib.ExportArgs { }, meta); diff --git a/Assets/VRM10/Samples~/VRM10Viewer/Motions/BvhMotion.cs b/Assets/VRM10/Samples~/VRM10Viewer/Motions/BvhMotion.cs index ffb925bb9..0cdac4631 100644 --- a/Assets/VRM10/Samples~/VRM10Viewer/Motions/BvhMotion.cs +++ b/Assets/VRM10/Samples~/VRM10Viewer/Motions/BvhMotion.cs @@ -28,7 +28,10 @@ namespace UniVRM10.VRM10Viewer // create SkinnedMesh for bone visualize var animator = m_context.Root.GetComponent(); m_boxMan = SkeletonMeshUtility.CreateRenderer(animator); - var material = new Material(Shader.Find("Standard")); + var tmpPrimitive = GameObject.CreatePrimitive(PrimitiveType.Quad); + var defaultMaterial = tmpPrimitive.GetComponent().sharedMaterial; + var material = new Material(defaultMaterial); + GameObject.Destroy(tmpPrimitive); BoxMan.sharedMaterial = material; var mesh = BoxMan.sharedMesh; mesh.name = "box-man"; diff --git a/Assets/VRM10/Samples~/VRM10Viewer/VRM10TargetMover.cs b/Assets/VRM10/Samples~/VRM10Viewer/VRM10TargetMover.cs index 7a37f1349..9311c436f 100644 --- a/Assets/VRM10/Samples~/VRM10Viewer/VRM10TargetMover.cs +++ b/Assets/VRM10/Samples~/VRM10Viewer/VRM10TargetMover.cs @@ -1,5 +1,4 @@ using System.Collections; -using System.Collections.Generic; using UnityEngine; diff --git a/Assets/VRM10/Samples~/VRM10Viewer/VRM10Viewer.unity b/Assets/VRM10/Samples~/VRM10Viewer/VRM10Viewer.unity index 54855ea3b..8e51e00c9 100644 --- a/Assets/VRM10/Samples~/VRM10Viewer/VRM10Viewer.unity +++ b/Assets/VRM10/Samples~/VRM10Viewer/VRM10Viewer.unity @@ -867,82 +867,6 @@ Transform: m_Father: {fileID: 0} m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &251940583 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 251940584} - - component: {fileID: 251940586} - - component: {fileID: 251940585} - m_Layer: 5 - m_Name: Checkmark - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!224 &251940584 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 251940583} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 452923209} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0.5, y: 0.5} - m_AnchorMax: {x: 0.5, y: 0.5} - m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 20, y: 20} - m_Pivot: {x: 0.5, y: 0.5} ---- !u!114 &251940585 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 251940583} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 0} - m_Color: {r: 1, g: 1, b: 1, a: 1} - m_RaycastTarget: 1 - m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} - m_Maskable: 1 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_Sprite: {fileID: 10901, guid: 0000000000000000f000000000000000, type: 0} - m_Type: 0 - m_PreserveAspect: 0 - m_FillCenter: 1 - m_FillMethod: 4 - m_FillAmount: 1 - m_FillClockwise: 1 - m_FillOrigin: 0 - m_UseSpriteMesh: 0 - m_PixelsPerUnitMultiplier: 1 ---- !u!222 &251940586 -CanvasRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 251940583} - m_CullTransparentMesh: 0 --- !u!1 &284921870 GameObject: m_ObjectHideFlags: 0 @@ -1113,11 +1037,9 @@ GameObject: serializedVersion: 6 m_Component: - component: {fileID: 322182885} - - component: {fileID: 322182888} - - component: {fileID: 322182887} - component: {fileID: 322182886} m_Layer: 0 - m_Name: Plane + m_Name: Floor m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 @@ -1138,70 +1060,19 @@ Transform: m_Father: {fileID: 0} m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!23 &322182886 -MeshRenderer: +--- !u!114 &322182886 +MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 322182884} m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_StaticShadowCaster: 0 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RayTraceProcedural: 0 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 1 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 0 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 - m_AdditionalVertexStreams: {fileID: 0} ---- !u!64 &322182887 -MeshCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 322182884} - m_Material: {fileID: 0} - m_IsTrigger: 0 - m_Enabled: 1 - serializedVersion: 4 - m_Convex: 0 - m_CookingOptions: 30 - m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} ---- !u!33 &322182888 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 322182884} - m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 1e6b73d090be404cad1a0e9839366ce2, type: 3} + m_Name: + m_EditorClassIdentifier: + _primitiveType: 4 --- !u!1 &339774396 GameObject: m_ObjectHideFlags: 0 @@ -1250,7 +1121,6 @@ RectTransform: - {fileID: 634488421} - {fileID: 1767738854} - {fileID: 103723704} - - {fileID: 1438613464} - {fileID: 602093298} m_Father: {fileID: 124675794} m_RootOrder: 0 @@ -1480,83 +1350,6 @@ RectTransform: m_AnchoredPosition: {x: 0, y: 0} m_SizeDelta: {x: 20, y: 20} m_Pivot: {x: 0.5, y: 0.5} ---- !u!1 &452923208 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 452923209} - - component: {fileID: 452923211} - - component: {fileID: 452923210} - m_Layer: 5 - m_Name: Background - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!224 &452923209 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 452923208} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: - - {fileID: 251940584} - m_Father: {fileID: 1438613464} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 1} - m_AnchorMax: {x: 0, y: 1} - m_AnchoredPosition: {x: 10, y: -10} - m_SizeDelta: {x: 20, y: 20} - m_Pivot: {x: 0.5, y: 0.5} ---- !u!114 &452923210 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 452923208} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 0} - m_Color: {r: 1, g: 1, b: 1, a: 1} - m_RaycastTarget: 1 - m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} - m_Maskable: 1 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} - m_Type: 1 - m_PreserveAspect: 0 - m_FillCenter: 1 - m_FillMethod: 4 - m_FillAmount: 1 - m_FillClockwise: 1 - m_FillOrigin: 0 - m_UseSpriteMesh: 0 - m_PixelsPerUnitMultiplier: 1 ---- !u!222 &452923211 -CanvasRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 452923208} - m_CullTransparentMesh: 0 --- !u!1 &488934504 GameObject: m_ObjectHideFlags: 0 @@ -1905,7 +1698,7 @@ RectTransform: - {fileID: 154330168} - {fileID: 1954133885} m_Father: {fileID: 339774397} - m_RootOrder: 18 + m_RootOrder: 17 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -2533,10 +2326,8 @@ GameObject: serializedVersion: 6 m_Component: - component: {fileID: 802105004} - - component: {fileID: 802105003} - - component: {fileID: 802105002} - - component: {fileID: 802105001} - component: {fileID: 802105005} + - component: {fileID: 802105006} m_Layer: 5 m_Name: LookAtTarget m_TagString: Untagged @@ -2544,69 +2335,6 @@ GameObject: m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!23 &802105001 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 802105000} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_StaticShadowCaster: 0 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RayTraceProcedural: 0 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 1 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 0 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 - m_AdditionalVertexStreams: {fileID: 0} ---- !u!135 &802105002 -SphereCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 802105000} - m_Material: {fileID: 0} - m_IsTrigger: 0 - m_Enabled: 1 - serializedVersion: 2 - m_Radius: 0.5 - m_Center: {x: 0, y: 0, z: 0} ---- !u!33 &802105003 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 802105000} - m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0} --- !u!4 &802105004 Transform: m_ObjectHideFlags: 0 @@ -2638,6 +2366,19 @@ MonoBehaviour: m_angularVelocity: 40 m_y: 1.5 m_height: 3 +--- !u!114 &802105006 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 802105000} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 1e6b73d090be404cad1a0e9839366ce2, type: 3} + m_Name: + m_EditorClassIdentifier: + _primitiveType: 0 --- !u!1 &806723448 GameObject: m_ObjectHideFlags: 0 @@ -5617,93 +5358,6 @@ CanvasRenderer: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1434602808} m_CullTransparentMesh: 0 ---- !u!1 &1438613463 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1438613464} - - component: {fileID: 1438613465} - m_Layer: 5 - m_Name: UseUrpMaterial - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!224 &1438613464 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1438613463} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: - - {fileID: 452923209} - - {fileID: 2090837017} - m_Father: {fileID: 339774397} - m_RootOrder: 17 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 0} - m_AnchorMax: {x: 0, y: 0} - m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 162, y: 20} - m_Pivot: {x: 0.5, y: 0.5} ---- !u!114 &1438613465 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1438613463} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 9085046f02f69544eb97fd06b6048fe2, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Navigation: - m_Mode: 3 - m_WrapAround: 0 - m_SelectOnUp: {fileID: 0} - m_SelectOnDown: {fileID: 0} - m_SelectOnLeft: {fileID: 0} - m_SelectOnRight: {fileID: 0} - m_Transition: 1 - m_Colors: - m_NormalColor: {r: 1, g: 1, b: 1, a: 1} - m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} - m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} - m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} - m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} - m_ColorMultiplier: 1 - m_FadeDuration: 0.1 - m_SpriteState: - m_HighlightedSprite: {fileID: 0} - m_PressedSprite: {fileID: 0} - m_SelectedSprite: {fileID: 0} - m_DisabledSprite: {fileID: 0} - m_AnimationTriggers: - m_NormalTrigger: Normal - m_HighlightedTrigger: Highlighted - m_PressedTrigger: Pressed - m_SelectedTrigger: Highlighted - m_DisabledTrigger: Disabled - m_Interactable: 1 - m_TargetGraphic: {fileID: 452923210} - toggleTransition: 1 - graphic: {fileID: 251940585} - m_Group: {fileID: 0} - onValueChanged: - m_PersistentCalls: - m_Calls: [] - m_IsOn: 0 --- !u!1 &1476033060 GameObject: m_ObjectHideFlags: 0 @@ -6033,6 +5687,7 @@ GameObject: - component: {fileID: 1629460661} - component: {fileID: 1629460658} - component: {fileID: 1629460657} + - component: {fileID: 1629460663} m_Layer: 0 m_Name: Main Camera m_TagString: MainCamera @@ -6121,6 +5776,39 @@ Transform: m_Father: {fileID: 241398689} m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1629460663 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1629460656} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: a79441f348de89743a2939f4d699eac1, type: 3} + m_Name: + m_EditorClassIdentifier: + m_RenderShadows: 1 + m_RequiresDepthTextureOption: 2 + m_RequiresOpaqueTextureOption: 2 + m_CameraType: 0 + m_Cameras: [] + m_RendererIndex: -1 + m_VolumeLayerMask: + serializedVersion: 2 + m_Bits: 1 + m_VolumeTrigger: {fileID: 0} + m_VolumeFrameworkUpdateModeOption: 2 + m_RenderPostProcessing: 0 + m_Antialiasing: 0 + m_AntialiasingQuality: 2 + m_StopNaN: 0 + m_Dithering: 0 + m_ClearDepth: 1 + m_AllowXRRendering: 1 + m_RequiresDepthTexture: 0 + m_RequiresColorTexture: 0 + m_Version: 2 --- !u!1 &1633219307 GameObject: m_ObjectHideFlags: 0 @@ -6828,7 +6516,6 @@ MonoBehaviour: m_enableLipSync: {fileID: 935566650} m_enableAutoBlink: {fileID: 634488422} m_enableAutoExpression: {fileID: 1767738855} - m_useUrpMaterial: {fileID: 1438613465} m_useAsync: {fileID: 602093299} m_target: {fileID: 802105000} m_motion: {fileID: 4900000, guid: 08df5151e71aed748b13547492fb8b9a, type: 3} @@ -7771,86 +7458,6 @@ CanvasRenderer: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 2055567528} m_CullTransparentMesh: 1 ---- !u!1 &2090837016 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 2090837017} - - component: {fileID: 2090837019} - - component: {fileID: 2090837018} - m_Layer: 5 - m_Name: Label - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!224 &2090837017 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2090837016} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 1438613464} - m_RootOrder: 1 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 0} - m_AnchorMax: {x: 1, y: 1} - m_AnchoredPosition: {x: 9, y: -0.5} - m_SizeDelta: {x: -28, y: -3} - m_Pivot: {x: 0.5, y: 0.5} ---- !u!114 &2090837018 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2090837016} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 0} - m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} - m_RaycastTarget: 1 - m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} - m_Maskable: 1 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_FontData: - m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} - m_FontSize: 14 - m_FontStyle: 0 - m_BestFit: 0 - m_MinSize: 10 - m_MaxSize: 40 - m_Alignment: 0 - m_AlignByGeometry: 0 - m_RichText: 1 - m_HorizontalOverflow: 0 - m_VerticalOverflow: 0 - m_LineSpacing: 1 - m_Text: Use URP Material ---- !u!222 &2090837019 -CanvasRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2090837016} - m_CullTransparentMesh: 0 --- !u!1 &2105159131 GameObject: m_ObjectHideFlags: 0 @@ -7942,6 +7549,7 @@ GameObject: m_Component: - component: {fileID: 2141451818} - component: {fileID: 2141451817} + - component: {fileID: 2141451819} m_Layer: 0 m_Name: Directional Light m_TagString: Untagged @@ -8026,3 +7634,23 @@ Transform: m_Father: {fileID: 0} m_RootOrder: 3 m_LocalEulerAnglesHint: {x: 50, y: -210, z: 0} +--- !u!114 &2141451819 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2141451816} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 474bcb49853aa07438625e644c072ee6, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Version: 1 + m_UsePipelineSettings: 1 + m_AdditionalLightsShadowResolutionTier: 2 + m_LightLayerMask: 1 + m_CustomShadowLayers: 0 + m_ShadowLayerMask: 1 + m_LightCookieSize: {x: 1, y: 1} + m_LightCookieOffset: {x: 0, y: 0} diff --git a/Assets/VRM10/Samples~/VRM10Viewer/VRM10ViewerUI.cs b/Assets/VRM10/Samples~/VRM10Viewer/VRM10ViewerUI.cs index f0f842ae2..91595b59f 100644 --- a/Assets/VRM10/Samples~/VRM10Viewer/VRM10ViewerUI.cs +++ b/Assets/VRM10/Samples~/VRM10Viewer/VRM10ViewerUI.cs @@ -5,7 +5,6 @@ using System.Threading; using UniGLTF; using UnityEngine; using UnityEngine.UI; -using VRMShaders; namespace UniVRM10.VRM10Viewer { @@ -42,9 +41,6 @@ namespace UniVRM10.VRM10Viewer [SerializeField] Toggle m_enableAutoExpression = default; - [SerializeField] - Toggle m_useUrpMaterial = default; - [SerializeField] Toggle m_useAsync = default; @@ -270,7 +266,6 @@ namespace UniVRM10.VRM10Viewer m_enableLipSync = toggles.First(x => x.name == "EnableLipSync"); m_enableAutoBlink = toggles.First(x => x.name == "EnableAutoBlink"); m_enableAutoExpression = toggles.First(x => x.name == "EnableAutoExpression"); - m_useUrpMaterial = toggles.First(x => x.name == "UseUrpMaterial"); m_useAsync = toggles.First(x => x.name == "UseAsync"); #if UNITY_2022_3_OR_NEWER @@ -545,8 +540,7 @@ namespace UniVRM10.VRM10Viewer var vrm10Instance = await Vrm10.LoadPathAsync(path, canLoadVrm0X: true, showMeshes: false, - awaitCaller: m_useAsync.enabled ? (IAwaitCaller)new RuntimeOnlyAwaitCaller() : (IAwaitCaller)new ImmediateCaller(), - materialGenerator: GetVrmMaterialDescriptorGenerator(m_useUrpMaterial.isOn), + awaitCaller: m_useAsync.enabled ? new RuntimeOnlyAwaitCaller() : new ImmediateCaller(), vrmMetaInformationCallback: m_texts.UpdateMeta, ct: cancellationToken); if (cancellationToken.IsCancellationRequested) diff --git a/Assets/VRM10/Samples~/VRM10Viewer/VRM10VisualPrimitive.cs b/Assets/VRM10/Samples~/VRM10Viewer/VRM10VisualPrimitive.cs new file mode 100644 index 000000000..05ea35def --- /dev/null +++ b/Assets/VRM10/Samples~/VRM10Viewer/VRM10VisualPrimitive.cs @@ -0,0 +1,27 @@ +using UnityEngine; + +namespace UniVRM10.VRM10Viewer +{ + /// + /// Built-in RP と URP の差異を楽に吸収してプリミティブを表示するためのクラス + /// + public class VRM10VisualPrimitive : MonoBehaviour + { + [SerializeField] private PrimitiveType _primitiveType; + + public PrimitiveType PrimitiveType + { + get => _primitiveType; + set => _primitiveType = value; + } + + private void Start() + { + var visual = GameObject.CreatePrimitive(_primitiveType); + visual.transform.SetParent(transform); + visual.transform.localPosition = Vector3.zero; + visual.transform.localRotation = Quaternion.identity; + visual.transform.localScale = Vector3.one; + } + } +} \ No newline at end of file diff --git a/Assets/VRM10/Samples~/VRM10Viewer/VRM10VisualPrimitive.cs.meta b/Assets/VRM10/Samples~/VRM10Viewer/VRM10VisualPrimitive.cs.meta new file mode 100644 index 000000000..d99639d67 --- /dev/null +++ b/Assets/VRM10/Samples~/VRM10Viewer/VRM10VisualPrimitive.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 1e6b73d090be404cad1a0e9839366ce2 +timeCreated: 1721736320 \ No newline at end of file diff --git a/Assets/VRM10/Tests/ApiSampleTests.cs b/Assets/VRM10/Tests/ApiSampleTests.cs index cc50aec15..3f9d1f58f 100644 --- a/Assets/VRM10/Tests/ApiSampleTests.cs +++ b/Assets/VRM10/Tests/ApiSampleTests.cs @@ -7,49 +7,20 @@ namespace UniVRM10.Test { public class ApiSampleTests { - 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; - } - - GameObject BuildGameObject(Vrm10Data data, bool showMesh) - { - using (var loader = new Vrm10Importer(data, null)) - { - var loaded = loader.Load(); - if (showMesh) - { - loaded.ShowMeshes(); - } - loaded.EnableUpdateWhenOffscreen(); - return loaded.gameObject; - } - } - [Test] public void Sample() { var path = "Tests/Models/Alicia_vrm-0.51/AliciaSolid_vrm-0.51.vrm"; Debug.Log($"load: {path}"); - using (var data = new GlbFileParser(path).Parse()) - using (var migrated = Vrm10Data.Migrate(data, out Vrm10Data result, out MigrationData migration)) - { - Assert.NotNull(result); + var instance = TestVrm10.LoadPathAsBuiltInRP(path, canLoadVrm0X: true); + Assert.NotNull(instance); - var go = BuildGameObject(result, true); - Debug.Log(go); + var go = instance.gameObject; + Debug.Log(go); - // export - var vrmBytes = Vrm10Exporter.Export(go, textureSerializer: new EditorTextureSerializer()); - - Debug.Log($"export {vrmBytes.Length} bytes"); - } + var vrmBytes = TestVrm10.ExportAsBuiltInRP(go); + Debug.Log($"export {vrmBytes.Length} bytes"); } } } diff --git a/Assets/VRM10/Tests/LoadTests.cs b/Assets/VRM10/Tests/LoadTests.cs index 02e1deee2..18caa14f7 100644 --- a/Assets/VRM10/Tests/LoadTests.cs +++ b/Assets/VRM10/Tests/LoadTests.cs @@ -1,5 +1,8 @@ +using System.IO; +using System.Linq; using NUnit.Framework; using UniGLTF; +using UnityEngine; namespace UniVRM10.Test { @@ -25,5 +28,109 @@ namespace UniVRM10.Test } } } + + static string ModelPath + { + get + { + // submodule + return Path.GetFullPath(Application.dataPath + "/../vrm-specification/samples/Seed-san/vrm/Seed-san.vrm") + .Replace("\\", "/"); + } + } + + static int getByteLength(glTF gltf, int accessorIndex) + { + if (accessorIndex < 0) { return 0; } + var accessor = gltf.accessors[accessorIndex]; + return accessor.CalcByteSize(); + } + + static int getByteLength(glTF gltf, glTFPrimitives prim) + { + var l = 0; + l += getByteLength(gltf, prim.indices); + l += getByteLength(gltf, prim.attributes.POSITION); + l += getByteLength(gltf, prim.attributes.NORMAL); + l += getByteLength(gltf, prim.attributes.TANGENT); + l += getByteLength(gltf, prim.attributes.TEXCOORD_0); + l += getByteLength(gltf, prim.attributes.JOINTS_0); + l += getByteLength(gltf, prim.attributes.WEIGHTS_0); + foreach (var morph in prim.targets) + { + l += getByteLength(gltf, morph.POSITION); + l += getByteLength(gltf, morph.NORMAL); + l += getByteLength(gltf, morph.TANGENT); + } + return l; + } + + static int getByteLength(glTF gltf, glTFMesh mesh) + { + var l = 0; + foreach (var prim in mesh.primitives) + { + l += getByteLength(gltf, prim); + } + return l; + } + + [Test] + public void NoTexture() + { + if (!File.Exists(ModelPath)) + { + return; + } + + // load model + var task = Vrm10.LoadPathAsync(ModelPath, awaitCaller: new ImmediateCaller()); + var instance = task.Result; + + // remove textures + instance.Vrm.Meta.Thumbnail = null; + var m = new Material(Shader.Find("Unlit/Color")); + foreach (var r in instance.GetComponentsInChildren()) + { + r.sharedMaterials = r.sharedMaterials.Select(x => m).ToArray(); + } + + // export as vrm1 + using (var arrayManager = new NativeArrayManager()) + { + var converter = new UniVRM10.ModelExporter(); + var model = converter.Export(arrayManager, instance.gameObject); + + // 右手系に変換 + Debug.Log($"convert to right handed coordinate..."); + model.ConvertCoordinate(VrmLib.Coordinates.Vrm1, ignoreVrm: false); + + // export vrm-1.0 + var exporter = new Vrm10Exporter(new GltfExportSettings()); + exporter.Export(instance.gameObject, model, converter, new VrmLib.ExportArgs + { + sparse = false, + }); + + var gltf = exporter.Storage.Gltf; + + var last = gltf.bufferViews.Last(); + // https://github.com/vrm-c/UniVRM/pull/2413 + Assert.AreEqual(last.byteOffset + last.byteLength, exporter.Storage.Gltf.buffers[0].byteLength); + + // check byteLength + var expected = 0; + foreach (var mesh in gltf.meshes) + { + expected += getByteLength(gltf, mesh); + } + foreach (var skin in gltf.skins) + { + expected += getByteLength(gltf, skin.inverseBindMatrices); + } + // alighment ? + // Assert.AreEqual(expected, exporter.Storage.Gltf.buffers[0].byteLength); + } + } } } diff --git a/Assets/VRM10/Tests/MigrationTests.cs b/Assets/VRM10/Tests/MigrationTests.cs index 09add1b02..999584449 100644 --- a/Assets/VRM10/Tests/MigrationTests.cs +++ b/Assets/VRM10/Tests/MigrationTests.cs @@ -197,7 +197,7 @@ namespace UniVRM10 { try { - Vrm10.LoadPathAsync(gltf.FullName, true, controlRigGenerationOption: ControlRigGenerationOption.None).Wait(); + TestVrm10.LoadPathAsBuiltInRP(gltf.FullName); } catch (UnNormalizedException) { @@ -372,7 +372,7 @@ namespace UniVRM10 new Color(2.0f, 2.0f, 2.0f, 1), }; - var instance106 = Vrm10.LoadBytesAsync(model106, awaitCaller: new ImmediateCaller()).Result; + var instance106 = TestVrm10.LoadBytesAsBuiltInRP(model106); var materials106 = instance106.GetComponent().Materials; Assert.AreEqual(materialCount, materials106.Count); for (var idx = 0; idx < materialCount; ++idx) @@ -384,7 +384,7 @@ namespace UniVRM10 if (correctEmissions[idx].HasValue) AssertAreApproximatelyEqualColor(correctEmissions[idx].Value, material.GetColor(emissionName)); } - var instance107 = Vrm10.LoadBytesAsync(model107, awaitCaller: new ImmediateCaller()).Result; + var instance107 = TestVrm10.LoadBytesAsBuiltInRP(model107); var materials107 = instance107.GetComponent().Materials; Assert.AreEqual(materialCount, materials107.Count); for (var idx = 0; idx < materialCount; ++idx) diff --git a/Assets/VRM10/Tests/TestAsset.cs b/Assets/VRM10/Tests/TestAsset.cs index 6077c2c44..5982583ee 100644 --- a/Assets/VRM10/Tests/TestAsset.cs +++ b/Assets/VRM10/Tests/TestAsset.cs @@ -16,10 +16,7 @@ namespace UniVRM10 public static Vrm10Instance LoadAlicia() { - var task = Vrm10.LoadPathAsync(AliciaPath, canLoadVrm0X: true); - task.Wait(); - var instance = task.Result; - + var instance = TestVrm10.LoadPathAsBuiltInRP(AliciaPath, canLoadVrm0X: true); return instance.GetComponent(); } } diff --git a/Assets/VRM10/Tests/TestVrm10.cs b/Assets/VRM10/Tests/TestVrm10.cs new file mode 100644 index 000000000..108c6d321 --- /dev/null +++ b/Assets/VRM10/Tests/TestVrm10.cs @@ -0,0 +1,37 @@ +using UniGLTF; +using UnityEngine; + +namespace UniVRM10 +{ + public static class TestVrm10 + { + public static Vrm10Instance LoadBytesAsBuiltInRP(byte[] bytes, bool canLoadVrm0X = true) + { + return Vrm10.LoadBytesAsync( + bytes, + canLoadVrm0X: canLoadVrm0X, + awaitCaller: new ImmediateCaller(), + materialGenerator: new BuiltInVrm10MaterialDescriptorGenerator() + ).Result; + } + + public static Vrm10Instance LoadPathAsBuiltInRP(string path, bool canLoadVrm0X = true) + { + return Vrm10.LoadPathAsync( + path, + canLoadVrm0X: canLoadVrm0X, + awaitCaller: new ImmediateCaller(), + materialGenerator: new BuiltInVrm10MaterialDescriptorGenerator() + ).Result; + } + + public static byte[] ExportAsBuiltInRP(GameObject gameObject) + { + return Vrm10Exporter.Export( + gameObject, + materialExporter: new BuiltInVrm10MaterialExporter(), + textureSerializer: new EditorTextureSerializer() + ); + } + } +} \ No newline at end of file diff --git a/Assets/VRM10/Tests/TestVrm10.cs.meta b/Assets/VRM10/Tests/TestVrm10.cs.meta new file mode 100644 index 000000000..69837185f --- /dev/null +++ b/Assets/VRM10/Tests/TestVrm10.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 4c9e0897ac194db3b7a55132871e6d75 +timeCreated: 1722265007 \ No newline at end of file diff --git a/Assets/VRM10/package.json b/Assets/VRM10/package.json index 3e977bd0d..a53cda1ba 100644 --- a/Assets/VRM10/package.json +++ b/Assets/VRM10/package.json @@ -1,6 +1,6 @@ { "name": "com.vrmc.vrm", - "version": "0.124.2", + "version": "0.125.0", "displayName": "VRM-1.0", "description": "VRM-1.0 importer", "unity": "2021.3", @@ -14,7 +14,7 @@ "name": "VRM Consortium" }, "dependencies": { - "com.vrmc.gltf": "0.124.2" + "com.vrmc.gltf": "0.125.0" }, "samples": [ { diff --git a/ProjectSettings/UnityConnectSettings.asset b/ProjectSettings/UnityConnectSettings.asset index ec1ab2929..a88bee0f1 100644 --- a/ProjectSettings/UnityConnectSettings.asset +++ b/ProjectSettings/UnityConnectSettings.asset @@ -3,30 +3,34 @@ --- !u!310 &1 UnityConnectSettings: m_ObjectHideFlags: 0 + serializedVersion: 1 m_Enabled: 0 m_TestMode: 0 - m_TestEventUrl: - m_TestConfigUrl: + m_EventOldUrl: https://api.uca.cloud.unity3d.com/v1/events + m_EventUrl: https://cdp.cloud.unity3d.com/v1/events + m_ConfigUrl: https://config.uca.cloud.unity3d.com + m_DashboardUrl: https://dashboard.unity3d.com m_TestInitMode: 0 CrashReportingSettings: - m_EventUrl: https://perf-events.cloud.unity3d.com/api/events/crashes + m_EventUrl: https://perf-events.cloud.unity3d.com m_Enabled: 0 + m_LogBufferSize: 10 m_CaptureEditorExceptions: 1 UnityPurchasingSettings: m_Enabled: 0 m_TestMode: 0 UnityAnalyticsSettings: m_Enabled: 0 - m_InitializeOnStartup: 1 m_TestMode: 0 - m_TestEventUrl: - m_TestConfigUrl: + m_InitializeOnStartup: 1 + m_PackageRequiringCoreStatsPresent: 0 UnityAdsSettings: m_Enabled: 0 m_InitializeOnStartup: 1 m_TestMode: 0 - m_EnabledPlatforms: 4294967295 m_IosGameId: m_AndroidGameId: + m_GameIds: {} + m_GameId: PerformanceReportingSettings: m_Enabled: 0 diff --git a/README.md b/README.md index 098cdcec7..387644f83 100644 --- a/README.md +++ b/README.md @@ -91,17 +91,14 @@ From the [latest release](https://github.com/vrm-c/UniVRM/releases/latest), you - For import/export VRM 1.0 - You have to install all of the following UPM packages: - - `com.vrmc.vrmshaders` - `com.vrmc.gltf` - `com.vrmc.vrm` - For import/export VRM 0.x - You have to install all of the following UPM packages: - - `com.vrmc.vrmshaders` - `com.vrmc.gltf` - `com.vrmc.univrm` - For import/export glTF 2.0 - You have to install all of the following UPM packages: - - `com.vrmc.vrmshaders` - `com.vrmc.gltf` You can install these UPM packages via `Package Manager` -> `+` -> `Add package from git URL...` in UnityEditor.