mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-04-24 15:08:02 -05:00
Merge pull request #872 from ousttrue/feature/extract_key
Feature/extract key
This commit is contained in:
commit
ed0cfb1f27
|
|
@ -50,33 +50,25 @@ namespace UniGLTF
|
|||
s_foldMaterials = EditorGUILayout.Foldout(s_foldMaterials, "Remapped Materials");
|
||||
if (s_foldMaterials)
|
||||
{
|
||||
importer.DrawRemapGUI<UnityEngine.Material>(parser.GLTF.materials.Select(x => x.name));
|
||||
importer.DrawRemapGUI<UnityEngine.Material>(parser.GLTF.materials.Select(x => new SubAssetKey(typeof(Material), x.name)));
|
||||
}
|
||||
|
||||
s_foldTextures = EditorGUILayout.Foldout(s_foldTextures, "Remapped Textures");
|
||||
if (s_foldTextures)
|
||||
{
|
||||
var names = enumTextures(parser)
|
||||
.Select(x =>
|
||||
importer.DrawRemapGUI<UnityEngine.Texture2D>(enumTextures(parser)
|
||||
.Where(x =>
|
||||
{
|
||||
if (x.TextureType != TextureImportTypes.StandardMap && !string.IsNullOrEmpty(x.Uri))
|
||||
var (key, param) = x;
|
||||
if ((param.TextureType == TextureImportTypes.sRGB || param.TextureType == TextureImportTypes.NormalMap) && !string.IsNullOrEmpty(param.Uri))
|
||||
{
|
||||
// GLTF の 無変換テクスチャーをスキップする
|
||||
return null;
|
||||
}
|
||||
|
||||
switch (x.TextureType)
|
||||
{
|
||||
case TextureImportTypes.NormalMap:
|
||||
return x.GltfName;
|
||||
|
||||
default:
|
||||
return x.ConvertedName;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
})
|
||||
.Where(x => !string.IsNullOrEmpty(x))
|
||||
;
|
||||
importer.DrawRemapGUI<UnityEngine.Texture2D>(names);
|
||||
.Select(x => x.Key)
|
||||
);
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Clear"))
|
||||
|
|
@ -100,9 +92,9 @@ namespace UniGLTF
|
|||
return;
|
||||
}
|
||||
|
||||
Action<Texture2D> addRemap = externalObject =>
|
||||
Action<SubAssetKey, Texture2D> addRemap = (key, externalObject) =>
|
||||
{
|
||||
self.AddRemap(new AssetImporter.SourceAssetIdentifier(typeof(UnityEngine.Texture2D), externalObject.name), externalObject);
|
||||
self.AddRemap(new AssetImporter.SourceAssetIdentifier(key.Type, key.Name), externalObject);
|
||||
};
|
||||
Action<IEnumerable<UnityPath>> onCompleted = _ =>
|
||||
{
|
||||
|
|
@ -133,9 +125,9 @@ namespace UniGLTF
|
|||
Directory.CreateDirectory(path);
|
||||
}
|
||||
|
||||
foreach (var asset in importer.GetSubAssets<Material>(importer.assetPath))
|
||||
foreach (var (key, asset) in importer.GetSubAssets<Material>(importer.assetPath))
|
||||
{
|
||||
asset.ExtractSubAsset($"{path}/{asset.name}.mat", false);
|
||||
asset.ExtractSubAsset($"{path}/{key.Name}.mat", false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,37 +23,34 @@ namespace UniGLTF
|
|||
AssetDatabase.ImportAsset(importer.assetPath, ImportAssetOptions.ForceUpdate);
|
||||
}
|
||||
|
||||
public static IEnumerable<T> GetSubAssets<T>(this ScriptedImporter importer, string assetPath) where T : UnityEngine.Object
|
||||
public static IEnumerable<(SubAssetKey, T)> GetSubAssets<T>(this ScriptedImporter importer, string assetPath) where T : UnityEngine.Object
|
||||
{
|
||||
return AssetDatabase
|
||||
.LoadAllAssetsAtPath(assetPath)
|
||||
.Where(x => AssetDatabase.IsSubAsset(x))
|
||||
.Where(x => x is T)
|
||||
.Select(x => x as T);
|
||||
.Select(x => (new SubAssetKey(typeof(T), x.name), x as T));
|
||||
}
|
||||
|
||||
public static void DrawRemapGUI<T>(this ScriptedImporter importer, IEnumerable<string> names) where T : UnityEngine.Object
|
||||
public static void DrawRemapGUI<T>(this ScriptedImporter importer, IEnumerable<SubAssetKey> keys) where T : UnityEngine.Object
|
||||
{
|
||||
EditorGUI.indentLevel++;
|
||||
{
|
||||
var map = importer.GetExternalObjectMap()
|
||||
.Select(x => (x.Key.name, x.Value as T))
|
||||
.Where(x => x.Item2 != null)
|
||||
.ToDictionary(x => x.Item1, x => x.Item2)
|
||||
;
|
||||
foreach (var name in names)
|
||||
var map = importer.GetExternalObjectMap();
|
||||
foreach (var key in keys)
|
||||
{
|
||||
if (string.IsNullOrEmpty(name))
|
||||
if (string.IsNullOrEmpty(key.Name))
|
||||
{
|
||||
throw new System.ArgumentNullException();
|
||||
continue;
|
||||
}
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
EditorGUILayout.PrefixLabel(name);
|
||||
map.TryGetValue(name, out T value);
|
||||
EditorGUILayout.PrefixLabel(key.Name);
|
||||
map.TryGetValue(new AssetImporter.SourceAssetIdentifier(key.Type, key.Name), out UnityEngine.Object value);
|
||||
var asset = EditorGUILayout.ObjectField(value, typeof(T), true) as T;
|
||||
if (asset != value)
|
||||
{
|
||||
// update
|
||||
importer.SetExternalUnityObject(new AssetImporter.SourceAssetIdentifier(value), asset);
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ namespace UniGLTF
|
|||
using (var loader = new ImporterContext(parser, externalObjectMap.Concat(externalTextures)))
|
||||
{
|
||||
// settings TextureImporters
|
||||
foreach (var textureInfo in GltfTextureEnumerator.EnumerateAllTexturesDistinct(parser))
|
||||
foreach (var (key, textureInfo) in GltfTextureEnumerator.EnumerateAllTexturesDistinct(parser))
|
||||
{
|
||||
TextureImporterConfigurator.Configure(textureInfo, loader.TextureFactory.ExternalMap);
|
||||
}
|
||||
|
|
@ -69,7 +69,7 @@ namespace UniGLTF
|
|||
GltfParser parser, UnityPath dir)
|
||||
{
|
||||
var used = new HashSet<Texture2D>();
|
||||
foreach (var texParam in GltfTextureEnumerator.EnumerateAllTexturesDistinct(parser))
|
||||
foreach (var (key, texParam) in GltfTextureEnumerator.EnumerateAllTexturesDistinct(parser))
|
||||
{
|
||||
switch (texParam.TextureType)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||
using System.IO;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using UniGLTF;
|
||||
using System.Linq;
|
||||
using VRMShaders;
|
||||
|
||||
|
|
@ -18,11 +19,11 @@ namespace UniGLTF
|
|||
public glTF GLTF => m_parser.GLTF;
|
||||
public IStorage Storage => m_parser.Storage;
|
||||
|
||||
public readonly Dictionary<UnityPath, TextureImportParam> Textures = new Dictionary<UnityPath, TextureImportParam>();
|
||||
UnityEngine.Texture2D[] m_subAssets;
|
||||
public readonly Dictionary<SubAssetKey, UnityPath> Textures = new Dictionary<SubAssetKey, UnityPath>();
|
||||
(SubAssetKey Key, UnityEngine.Texture2D Value)[] m_subAssets;
|
||||
UnityPath m_textureDirectory;
|
||||
|
||||
public TextureExtractor(GltfParser parser, UnityPath textureDirectory, UnityEngine.Texture2D[] subAssets)
|
||||
public TextureExtractor(GltfParser parser, UnityPath textureDirectory, (SubAssetKey, UnityEngine.Texture2D)[] subAssets)
|
||||
{
|
||||
m_parser = parser;
|
||||
m_textureDirectory = textureDirectory;
|
||||
|
|
@ -41,28 +42,29 @@ namespace UniGLTF
|
|||
return Path.GetExtension(uri).ToLower();
|
||||
}
|
||||
|
||||
public void Extract(TextureImportParam param)
|
||||
public void Extract(SubAssetKey key, TextureImportParam param)
|
||||
{
|
||||
if (Textures.Values.Contains(param))
|
||||
if (Textures.ContainsKey(key))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
UnityPath targetPath = default;
|
||||
if (!string.IsNullOrEmpty(param.Uri) && !param.ExtractConverted)
|
||||
{
|
||||
targetPath = m_textureDirectory.Child(param.GltfFileName);
|
||||
// use GLTF external
|
||||
// targetPath = m_textureDirectory.Child(key.Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
UnityPath targetPath = default;
|
||||
|
||||
switch (param.TextureType)
|
||||
{
|
||||
case TextureImportTypes.StandardMap:
|
||||
{
|
||||
// write converted texture
|
||||
var subAsset = m_subAssets.FirstOrDefault(x => x.name == param.ConvertedName);
|
||||
targetPath = m_textureDirectory.Child(param.ConvertedFileName);
|
||||
var (_, subAsset) = m_subAssets.FirstOrDefault(x => x.Equals(key));
|
||||
targetPath = m_textureDirectory.Child($"{key.Name}.png");
|
||||
File.WriteAllBytes(targetPath.FullPath, subAsset.EncodeToPNG().ToArray());
|
||||
targetPath.ImportAsset();
|
||||
break;
|
||||
|
|
@ -71,15 +73,14 @@ namespace UniGLTF
|
|||
default:
|
||||
{
|
||||
// write original bytes
|
||||
targetPath = m_textureDirectory.Child(param.GltfFileName);
|
||||
targetPath = m_textureDirectory.Child($"{key.Name}{param.Ext}");
|
||||
File.WriteAllBytes(targetPath.FullPath, param.Index0().Result.ToArray());
|
||||
targetPath.ImportAsset();
|
||||
break;
|
||||
}
|
||||
}
|
||||
Textures.Add(key, targetPath);
|
||||
}
|
||||
|
||||
Textures.Add(targetPath, param);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -93,37 +94,44 @@ namespace UniGLTF
|
|||
/// <param name="dirName"></param>
|
||||
/// <param name="onCompleted"></param>
|
||||
public static void ExtractTextures(GltfParser parser, UnityPath textureDirectory,
|
||||
EnumerateAllTexturesDistinctFunc textureEnumerator, Texture2D[] subAssets, Action<Texture2D> addRemap,
|
||||
EnumerateAllTexturesDistinctFunc textureEnumerator, (SubAssetKey, Texture2D)[] subAssets,
|
||||
Action<SubAssetKey, Texture2D> addRemap,
|
||||
Action<IEnumerable<UnityPath>> onCompleted = null)
|
||||
{
|
||||
var extractor = new TextureExtractor(parser, textureDirectory, subAssets);
|
||||
foreach (var x in textureEnumerator(parser))
|
||||
foreach (var (key, x) in textureEnumerator(parser))
|
||||
{
|
||||
extractor.Extract(x);
|
||||
extractor.Extract(key, x);
|
||||
}
|
||||
|
||||
EditorApplication.delayCall += () =>
|
||||
{
|
||||
// Wait for the texture assets to be imported
|
||||
|
||||
foreach (var kv in extractor.Textures)
|
||||
foreach (var (key, targetPath) in extractor.Textures)
|
||||
{
|
||||
var targetPath = kv.Key;
|
||||
var param = kv.Value;
|
||||
|
||||
// remap
|
||||
var externalObject = targetPath.LoadAsset<Texture2D>();
|
||||
if (externalObject != null)
|
||||
{
|
||||
addRemap(externalObject);
|
||||
addRemap(key, externalObject);
|
||||
}
|
||||
}
|
||||
|
||||
if (onCompleted != null)
|
||||
{
|
||||
onCompleted(extractor.Textures.Keys);
|
||||
onCompleted(extractor.Textures.Values);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public static class KeyValuePariExtensions
|
||||
{
|
||||
public static void Deconstruct<T, U>(this KeyValuePair<T, U> pair, out T key, out U value)
|
||||
{
|
||||
key = pair.Key;
|
||||
value = pair.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ namespace UniGLTF
|
|||
{
|
||||
case TextureImportTypes.NormalMap:
|
||||
{
|
||||
if (ExternalMap.TryGetValue(textureInfo.GltfName, out Texture2D external))
|
||||
if (ExternalMap.TryGetValue(textureInfo.UnityObjectName, out Texture2D external))
|
||||
{
|
||||
ConfigureSize(external);
|
||||
ConfigureNormalMap(external);
|
||||
|
|
@ -78,7 +78,7 @@ namespace UniGLTF
|
|||
|
||||
case TextureImportTypes.StandardMap:
|
||||
{
|
||||
if (ExternalMap.TryGetValue(textureInfo.ConvertedName, out Texture2D external))
|
||||
if (ExternalMap.TryGetValue(textureInfo.UnityObjectName, out Texture2D external))
|
||||
{
|
||||
ConfigureSize(external);
|
||||
ConfigureLinear(external);
|
||||
|
|
@ -88,7 +88,7 @@ namespace UniGLTF
|
|||
|
||||
case TextureImportTypes.sRGB:
|
||||
{
|
||||
if (ExternalMap.TryGetValue(textureInfo.GltfName, out Texture2D external))
|
||||
if (ExternalMap.TryGetValue(textureInfo.UnityObjectName, out Texture2D external))
|
||||
{
|
||||
ConfigureSize(external);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ namespace MeshUtility
|
|||
value = prefab;
|
||||
isPrefab = true;
|
||||
}
|
||||
catch (ArgumentException ex)
|
||||
catch (ArgumentException)
|
||||
{
|
||||
// Debug.LogWarning(ex);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,13 +49,13 @@ namespace UniGLTF
|
|||
Transparent
|
||||
}
|
||||
|
||||
public static TextureImportParam BaseColorTexture(GltfParser parser, glTFMaterial src)
|
||||
public static (SubAssetKey, TextureImportParam Param) BaseColorTexture(GltfParser parser, glTFMaterial src)
|
||||
{
|
||||
var (offset, scale) = GltfMaterialImporter.GetTextureOffsetAndScale(src.pbrMetallicRoughness.baseColorTexture);
|
||||
return GltfTextureImporter.CreateSRGB(parser, src.pbrMetallicRoughness.baseColorTexture.index, offset, scale);
|
||||
}
|
||||
|
||||
public static TextureImportParam StandardTexture(GltfParser parser, glTFMaterial src)
|
||||
public static (SubAssetKey, TextureImportParam) StandardTexture(GltfParser parser, glTFMaterial src)
|
||||
{
|
||||
var metallicFactor = 1.0f;
|
||||
var roughnessFactor = 1.0f;
|
||||
|
|
@ -65,15 +65,17 @@ namespace UniGLTF
|
|||
roughnessFactor = src.pbrMetallicRoughness.roughnessFactor;
|
||||
}
|
||||
var (offset, scale) = GltfMaterialImporter.GetTextureOffsetAndScale(src.pbrMetallicRoughness.metallicRoughnessTexture);
|
||||
return GltfTextureImporter.CreateStandard(parser,
|
||||
var param = GltfTextureImporter.CreateStandard(parser,
|
||||
src.pbrMetallicRoughness?.metallicRoughnessTexture?.index,
|
||||
src.occlusionTexture?.index,
|
||||
offset, scale,
|
||||
metallicFactor,
|
||||
roughnessFactor);
|
||||
var key = new SubAssetKey(typeof(Texture2D), param.UnityObjectName);
|
||||
return (key, param);
|
||||
}
|
||||
|
||||
public static TextureImportParam NormalTexture(GltfParser parser, glTFMaterial src)
|
||||
public static (SubAssetKey, TextureImportParam Param) NormalTexture(GltfParser parser, glTFMaterial src)
|
||||
{
|
||||
var (offset, scale) = GltfMaterialImporter.GetTextureOffsetAndScale(src.normalTexture);
|
||||
return GltfTextureImporter.CreateNormal(parser, src.normalTexture.index, offset, scale);
|
||||
|
|
@ -95,7 +97,8 @@ namespace UniGLTF
|
|||
{
|
||||
if (src.pbrMetallicRoughness.metallicRoughnessTexture != null || src.occlusionTexture != null)
|
||||
{
|
||||
standardParam = StandardTexture(parser, src);
|
||||
SubAssetKey key;
|
||||
(key, standardParam) = StandardTexture(parser, src);
|
||||
}
|
||||
|
||||
if (src.pbrMetallicRoughness.baseColorFactor != null && src.pbrMetallicRoughness.baseColorFactor.Length == 4)
|
||||
|
|
@ -106,7 +109,7 @@ namespace UniGLTF
|
|||
|
||||
if (src.pbrMetallicRoughness.baseColorTexture != null && src.pbrMetallicRoughness.baseColorTexture.index != -1)
|
||||
{
|
||||
var textureParam = BaseColorTexture(parser, src);
|
||||
var (key, textureParam) = BaseColorTexture(parser, src);
|
||||
param.TextureSlots.Add("_MainTex", textureParam);
|
||||
}
|
||||
|
||||
|
|
@ -128,7 +131,7 @@ namespace UniGLTF
|
|||
if (src.normalTexture != null && src.normalTexture.index != -1)
|
||||
{
|
||||
param.Actions.Add(material => material.EnableKeyword("_NORMALMAP"));
|
||||
var textureParam = NormalTexture(parser, src);
|
||||
var (key, textureParam) = NormalTexture(parser, src);
|
||||
param.TextureSlots.Add("_BumpMap", textureParam);
|
||||
param.FloatValues.Add("_BumpScale", src.normalTexture.scale);
|
||||
}
|
||||
|
|
@ -142,7 +145,8 @@ namespace UniGLTF
|
|||
if (src.emissiveFactor != null
|
||||
|| (src.emissiveTexture != null && src.emissiveTexture.index != -1))
|
||||
{
|
||||
param.Actions.Add(material => {
|
||||
param.Actions.Add(material =>
|
||||
{
|
||||
material.EnableKeyword("_EMISSION");
|
||||
material.globalIlluminationFlags &= ~MaterialGlobalIlluminationFlags.EmissiveIsBlack;
|
||||
});
|
||||
|
|
@ -155,12 +159,13 @@ namespace UniGLTF
|
|||
if (src.emissiveTexture != null && src.emissiveTexture.index != -1)
|
||||
{
|
||||
var (offset, scale) = GltfMaterialImporter.GetTextureOffsetAndScale(src.emissiveTexture);
|
||||
var textureParam = GltfTextureImporter.CreateSRGB(parser, src.emissiveTexture.index, offset, scale);
|
||||
var (key, textureParam) = GltfTextureImporter.CreateSRGB(parser, src.emissiveTexture.index, offset, scale);
|
||||
param.TextureSlots.Add("_EmissionMap", textureParam);
|
||||
}
|
||||
}
|
||||
|
||||
param.Actions.Add(material => {
|
||||
param.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)
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using VRMShaders;
|
||||
|
||||
|
||||
namespace UniGLTF
|
||||
{
|
||||
public delegate IEnumerable<TextureImportParam> EnumerateAllTexturesDistinctFunc(GltfParser parser);
|
||||
public delegate IEnumerable<(SubAssetKey Key, TextureImportParam Param)> EnumerateAllTexturesDistinctFunc(GltfParser parser);
|
||||
|
||||
/// <summary>
|
||||
/// Texture 生成に関して
|
||||
|
|
@ -12,29 +13,22 @@ namespace UniGLTF
|
|||
///
|
||||
/// * (gltf/glb/vrm-1): AssetImporterContext.AddObjectToAsset(SubAsset)
|
||||
/// * (gltf/glb/vrm-1): ScriptedImporter.GetExternalObjectMap(Extracted)
|
||||
/// * (vrm-0): (Extracted) ScriptedImporter では無いので ScriptedImporter.AddRemap が無い
|
||||
/// * (vrm-0): (Extracted) ScriptedImporter では無いので ScriptedImporter.AddRemap, GetExternalObjectMap が無い
|
||||
///
|
||||
/// Extract は外部ファイルに png/jpg のバイト列を出力して、TextureImporter を設定すること。ScriptedImporter.AddRemap
|
||||
/// Extracted は、
|
||||
/// AddRemap, GetExternalObjectMap は Dictionary[SourceAssetIdentifier, UnityEngine.Object] に対する API で
|
||||
/// SourceAssetIdentifier 型がリソースを識別するキーとなる。
|
||||
///
|
||||
/// ファイル名もしくはSubAsset名を介してテクスチャーアセットにアクセスるので、文字列をユニークなキーとしてテクスチャーを識別できる必要がある。
|
||||
/// 基本的に、gltf.textures と Texture2D が1対1に対応するので、 gltfTexture.name のユニーク性を確保した上で
|
||||
/// これを用いればよいが以下の例外がある。
|
||||
///
|
||||
/// * PBR の MetallicSmoothness と Occlusion が合体する場合
|
||||
/// * (gltf)外部テクスチャーファイルの uri 参照が同じになる場合(同じイメージファイルが異なるテクスチャー設定を保持するケースをサポートしない)
|
||||
/// * 異なる gltfTexture.source が 同じ gltfImage を参照する場合
|
||||
/// * 異なる gltfImage.uri が 同じ ファイルを参照する場合
|
||||
///
|
||||
/// 例外に対処した上で、ユニークなテクスチャー生成情報を列挙するのが
|
||||
/// gltfTexture から SourceAssetIdentifier を作り出すことで、GetExternalObjectMap との対応関係を作る。
|
||||
///
|
||||
/// GltfTextureEnumerator.Enumerate
|
||||
///
|
||||
/// である。
|
||||
/// [例外]
|
||||
/// glTF で外部ファイルを uri 参照する場合
|
||||
/// * sRGB 外部ファイルをそのまま使うので SubAsset にしない
|
||||
/// * normal 外部ライルをそのまま使うので SubAsset にしない(normalとしてロードするためにAssetImporterの設定は必用)
|
||||
/// * metallicRoughnessOcclusion 変換結果を SubAsset 化する
|
||||
/// </summary>
|
||||
public static class GltfTextureEnumerator
|
||||
{
|
||||
public static IEnumerable<TextureImportParam> EnumerateTexturesForMaterial(GltfParser parser, int i)
|
||||
public static IEnumerable<(SubAssetKey, TextureImportParam)> EnumerateTexturesForMaterial(GltfParser parser, int i)
|
||||
{
|
||||
var m = parser.GLTF.materials[i];
|
||||
|
||||
|
|
@ -86,16 +80,21 @@ namespace UniGLTF
|
|||
/// </summary>
|
||||
/// <param name="parser"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<TextureImportParam> EnumerateAllTexturesDistinct(GltfParser parser)
|
||||
public static IEnumerable<(SubAssetKey, TextureImportParam)> EnumerateAllTexturesDistinct(GltfParser parser)
|
||||
{
|
||||
var used = new HashSet<string>();
|
||||
var used = new HashSet<SubAssetKey>();
|
||||
Func<(SubAssetKey, TextureImportParam), bool> add = (kv) =>
|
||||
{
|
||||
var (key, textureInfo) = kv;
|
||||
return used.Add(key);
|
||||
};
|
||||
for (int i = 0; i < parser.GLTF.materials.Count; ++i)
|
||||
{
|
||||
foreach (var textureInfo in EnumerateTexturesForMaterial(parser, i))
|
||||
foreach (var kv in EnumerateTexturesForMaterial(parser, i))
|
||||
{
|
||||
if (used.Add(textureInfo.ExtractKey))
|
||||
if (add(kv))
|
||||
{
|
||||
yield return textureInfo;
|
||||
yield return kv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ namespace UniGLTF
|
|||
if (src.pbrMetallicRoughness.baseColorTexture != null)
|
||||
{
|
||||
var (offset, scale) = GltfMaterialImporter.GetTextureOffsetAndScale(src.pbrMetallicRoughness.baseColorTexture);
|
||||
var textureParam = GltfTextureImporter.CreateSRGB(parser, src.pbrMetallicRoughness.baseColorTexture.index, offset, scale);
|
||||
var (key, textureParam) = GltfTextureImporter.CreateSRGB(parser, src.pbrMetallicRoughness.baseColorTexture.index, offset, scale);
|
||||
param.TextureSlots.Add("_MainTex", textureParam);
|
||||
}
|
||||
|
||||
|
|
|
|||
35
Assets/UniGLTF/Runtime/UniGLTF/IO/SubAssetKey.cs
Normal file
35
Assets/UniGLTF/Runtime/UniGLTF/IO/SubAssetKey.cs
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
using System;
|
||||
|
||||
|
||||
namespace UniGLTF
|
||||
{
|
||||
/// <summary>
|
||||
/// UnityEditor.Experimental.AssetImporter.SourceAssetIdentifier に対応する
|
||||
///
|
||||
/// * SourceAssetIdentifier が UnityEditor なので、 Runtime でも使えるように
|
||||
/// * Type が違うが Name が同じだと警告が出る。例えば、Material と 同じ名前の Texture がある場合。
|
||||
/// Identifier uniqueness violation: 'Alicia_body'. Scripted Importers do not guarantee that subsequent imports of this asset will properly re-link to these targets.
|
||||
/// * なので、SourceAssetIdentifier は、$"{Type.Name}.{UnityObject.name}" のように強制的に Unique にするのが良さそう
|
||||
/// * 一方で、Extract したファイル名に $"{Type.Name}." が付属するのは煩わしいのでこれは無しにしたい。
|
||||
///
|
||||
/// public void AddRemap(SourceAssetIdentifier identifier, UnityEngine.Object externalObject);
|
||||
///
|
||||
/// の呼び出し時に、identifier.name と externalObject.name が同じでない運用にしてみる。
|
||||
///
|
||||
/// </summary>
|
||||
public struct SubAssetKey
|
||||
{
|
||||
public readonly Type Type;
|
||||
public readonly string Name;
|
||||
|
||||
public SubAssetKey(Type t, string name)
|
||||
{
|
||||
if (string.IsNullOrEmpty(name))
|
||||
{
|
||||
throw new System.ArgumentNullException();
|
||||
}
|
||||
Type = t;
|
||||
Name = name;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/UniGLTF/Runtime/UniGLTF/IO/SubAssetKey.cs.meta
Normal file
11
Assets/UniGLTF/Runtime/UniGLTF/IO/SubAssetKey.cs.meta
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0c9d1b62a112b9045beb99b48000b71e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -31,31 +31,40 @@ namespace UniGLTF
|
|||
}
|
||||
}
|
||||
|
||||
public static TextureImportParam CreateSRGB(GltfParser parser, int textureIndex, Vector2 offset, Vector2 scale)
|
||||
public static (SubAssetKey, TextureImportParam Param) CreateSRGB(GltfParser parser, int textureIndex, Vector2 offset, Vector2 scale)
|
||||
{
|
||||
var name = CreateNameExt(parser.GLTF, textureIndex, TextureImportTypes.sRGB);
|
||||
var gltfTexture = parser.GLTF.textures[textureIndex];
|
||||
var gltfImage = parser.GLTF.images[gltfTexture.source];
|
||||
var name = TextureImportName.GetUnityObjectName(TextureImportTypes.sRGB, gltfTexture.name, gltfImage.uri);
|
||||
var sampler = CreateSampler(parser.GLTF, textureIndex);
|
||||
GetTextureBytesAsync getTextureBytesAsync = () => Task.FromResult(ToArray(parser.GLTF.GetImageBytesFromTextureIndex(parser.Storage, textureIndex)));
|
||||
return new TextureImportParam(name, offset, scale, sampler, TextureImportTypes.sRGB, default, default, getTextureBytesAsync, default, default, default, default, default);
|
||||
var key = new SubAssetKey(typeof(Texture2D), name);
|
||||
var param = new TextureImportParam(name, gltfImage.GetExt(), gltfImage.uri, offset, scale, sampler, TextureImportTypes.sRGB, default, default, getTextureBytesAsync, default, default, default, default, default);
|
||||
return (key, param);
|
||||
}
|
||||
|
||||
public static TextureImportParam CreateNormal(GltfParser parser, int textureIndex, Vector2 offset, Vector2 scale)
|
||||
public static (SubAssetKey, TextureImportParam Param) CreateNormal(GltfParser parser, int textureIndex, Vector2 offset, Vector2 scale)
|
||||
{
|
||||
var name = CreateNameExt(parser.GLTF, textureIndex, TextureImportTypes.NormalMap);
|
||||
var gltfTexture = parser.GLTF.textures[textureIndex];
|
||||
var gltfImage = parser.GLTF.images[gltfTexture.source];
|
||||
var name = TextureImportName.GetUnityObjectName(TextureImportTypes.NormalMap, null, gltfImage.uri);
|
||||
var sampler = CreateSampler(parser.GLTF, textureIndex);
|
||||
GetTextureBytesAsync getTextureBytesAsync = () => Task.FromResult(ToArray(parser.GLTF.GetImageBytesFromTextureIndex(parser.Storage, textureIndex)));
|
||||
return new TextureImportParam(name, offset, scale, sampler, TextureImportTypes.NormalMap, default, default, getTextureBytesAsync, default, default, default, default, default);
|
||||
var key = new SubAssetKey(typeof(Texture2D), name);
|
||||
var param = new TextureImportParam(name, gltfImage.GetExt(), gltfImage.uri, offset, scale, sampler, TextureImportTypes.NormalMap, default, default, getTextureBytesAsync, default, default, default, default, default);
|
||||
return (key, param);
|
||||
}
|
||||
|
||||
public static TextureImportParam CreateStandard(GltfParser parser, int? metallicRoughnessTextureIndex, int? occlusionTextureIndex, Vector2 offset, Vector2 scale, float metallicFactor, float roughnessFactor)
|
||||
{
|
||||
TextureImportName name = default;
|
||||
string name = default;
|
||||
|
||||
GetTextureBytesAsync getMetallicRoughnessAsync = default;
|
||||
SamplerParam sampler = default;
|
||||
if (metallicRoughnessTextureIndex.HasValue)
|
||||
{
|
||||
name = CreateNameExt(parser.GLTF, metallicRoughnessTextureIndex.Value, TextureImportTypes.StandardMap);
|
||||
var gltfTexture = parser.GLTF.textures[metallicRoughnessTextureIndex.Value];
|
||||
name = TextureImportName.GetUnityObjectName(TextureImportTypes.StandardMap, gltfTexture.name, parser.GLTF.images[gltfTexture.source].uri);
|
||||
sampler = CreateSampler(parser.GLTF, metallicRoughnessTextureIndex.Value);
|
||||
getMetallicRoughnessAsync = () => Task.FromResult(ToArray(parser.GLTF.GetImageBytesFromTextureIndex(parser.Storage, metallicRoughnessTextureIndex.Value)));
|
||||
}
|
||||
|
|
@ -63,30 +72,16 @@ namespace UniGLTF
|
|||
GetTextureBytesAsync getOcclusionAsync = default;
|
||||
if (occlusionTextureIndex.HasValue)
|
||||
{
|
||||
if (string.IsNullOrEmpty(name.GltfName))
|
||||
var gltfTexture = parser.GLTF.textures[occlusionTextureIndex.Value];
|
||||
if (string.IsNullOrEmpty(name))
|
||||
{
|
||||
name = CreateNameExt(parser.GLTF, occlusionTextureIndex.Value, TextureImportTypes.StandardMap);
|
||||
name = TextureImportName.GetUnityObjectName(TextureImportTypes.StandardMap, gltfTexture.name, parser.GLTF.images[gltfTexture.source].uri);
|
||||
}
|
||||
sampler = CreateSampler(parser.GLTF, occlusionTextureIndex.Value);
|
||||
getOcclusionAsync = () => Task.FromResult(ToArray(parser.GLTF.GetImageBytesFromTextureIndex(parser.Storage, occlusionTextureIndex.Value)));
|
||||
}
|
||||
|
||||
return new TextureImportParam(name, offset, scale, sampler, TextureImportTypes.StandardMap, metallicFactor, roughnessFactor, getMetallicRoughnessAsync, getOcclusionAsync, default, default, default, default);
|
||||
}
|
||||
|
||||
public static TextureImportName CreateNameExt(glTF gltf, int textureIndex, TextureImportTypes textureType)
|
||||
{
|
||||
if (textureIndex < 0 || textureIndex >= gltf.textures.Count)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
var gltfTexture = gltf.textures[textureIndex];
|
||||
if (gltfTexture.source < 0 || gltfTexture.source >= gltf.images.Count)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
var gltfImage = gltf.images[gltfTexture.source];
|
||||
return new TextureImportName(textureType, gltfTexture.name, gltfImage.GetExt(), gltfImage.uri);
|
||||
return new TextureImportParam(name, ".png", null, offset, scale, sampler, TextureImportTypes.StandardMap, metallicFactor, roughnessFactor, getMetallicRoughnessAsync, getOcclusionAsync, default, default, default, default);
|
||||
}
|
||||
|
||||
public static SamplerParam CreateSampler(glTF gltf, int index)
|
||||
|
|
|
|||
|
|
@ -147,11 +147,11 @@ namespace VRM
|
|||
//
|
||||
var subAssets = m_context.TextureFactory.Textures
|
||||
.Where(x => x.IsUsed)
|
||||
.Select(x => x.Texture)
|
||||
.Select(x => (new SubAssetKey(typeof(Texture2D), x.Texture.name), x.Texture))
|
||||
.ToArray();
|
||||
var vrmTextures = new VRMMtoonMaterialImporter(m_context.VRM);
|
||||
var dirName = $"{m_prefabPath.FileNameWithoutExtension}.Textures";
|
||||
TextureExtractor.ExtractTextures(m_context.Parser, m_prefabPath.Parent.Child(dirName), vrmTextures.EnumerateAllTexturesDistinct, subAssets, _ => { }, onTextureReloaded);
|
||||
TextureExtractor.ExtractTextures(m_context.Parser, m_prefabPath.Parent.Child(dirName), vrmTextures.EnumerateAllTexturesDistinct, subAssets, (_x, _y) => { }, onTextureReloaded);
|
||||
}
|
||||
|
||||
bool SaveAsAsset(UnityEngine.Object o)
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ namespace VRM
|
|||
using (var context = new VRMImporterContext(parser, map))
|
||||
{
|
||||
var editor = new VRMEditorImporterContext(context, prefabPath);
|
||||
foreach (var textureInfo in new VRMMtoonMaterialImporter(context.VRM).EnumerateAllTexturesDistinct(parser))
|
||||
foreach (var (key, textureInfo) in new VRMMtoonMaterialImporter(context.VRM).EnumerateAllTexturesDistinct(parser))
|
||||
{
|
||||
TextureImporterConfigurator.Configure(textureInfo, map.ToDictionary(x => x.name, x => x.texture as Texture2D));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ namespace VRM
|
|||
using (var context = new VRMImporterContext(parser, map))
|
||||
{
|
||||
var editor = new VRMEditorImporterContext(context, prefabPath);
|
||||
foreach (var textureInfo in new VRMMtoonMaterialImporter(context.VRM).EnumerateAllTexturesDistinct(parser))
|
||||
foreach (var (key, textureInfo) in new VRMMtoonMaterialImporter(context.VRM).EnumerateAllTexturesDistinct(parser))
|
||||
{
|
||||
TextureImporterConfigurator.Configure(textureInfo, map.ToDictionary(x => x.name, x => x.texture as Texture2D));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ namespace VRM
|
|||
{
|
||||
public static class MToonTextureParam
|
||||
{
|
||||
public static TextureImportParam Create(GltfParser parser, int index, Vector2 offset, Vector2 scale, string prop, float metallicFactor, float roughnessFactor)
|
||||
public static (SubAssetKey, TextureImportParam) Create(GltfParser parser, int index, Vector2 offset, Vector2 scale, string prop, float metallicFactor, float roughnessFactor)
|
||||
{
|
||||
switch (prop)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -297,7 +297,8 @@ namespace VRM
|
|||
meta.Title = gltfMeta.title;
|
||||
if (gltfMeta.texture >= 0)
|
||||
{
|
||||
meta.Thumbnail = await TextureFactory.GetTextureAsync(GltfTextureImporter.CreateSRGB(Parser, gltfMeta.texture, Vector2.zero, Vector2.one));
|
||||
var (key, param) = GltfTextureImporter.CreateSRGB(Parser, gltfMeta.texture, Vector2.zero, Vector2.one);
|
||||
meta.Thumbnail = await TextureFactory.GetTextureAsync(param);
|
||||
}
|
||||
meta.AllowedUser = gltfMeta.allowedUser;
|
||||
meta.ViolentUssage = gltfMeta.violentUssage;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UniGLTF;
|
||||
using UnityEngine;
|
||||
using VRMShaders;
|
||||
|
|
@ -62,7 +63,7 @@ namespace VRM
|
|||
scale = new Vector2(value[2], value[3]);
|
||||
}
|
||||
|
||||
var textureParam = MToonTextureParam.Create(parser, kv.Value, offset, scale, kv.Key, 1, 1);
|
||||
var (key, textureParam) = MToonTextureParam.Create(parser, kv.Value, offset, scale, kv.Key, 1, 1);
|
||||
param.TextureSlots.Add(kv.Key, textureParam);
|
||||
}
|
||||
|
||||
|
|
@ -93,10 +94,10 @@ namespace VRM
|
|||
return true;
|
||||
}
|
||||
|
||||
public IEnumerable<TextureImportParam> EnumerateTexturesForMaterial(GltfParser parser, int i)
|
||||
public IEnumerable<(SubAssetKey, TextureImportParam)> EnumerateTexturesForMaterial(GltfParser parser, int i)
|
||||
{
|
||||
// mtoon
|
||||
if (!TryCreateParam(parser, i, out MaterialImportParam param))
|
||||
if (TryCreateParam(parser, i, out MaterialImportParam param))
|
||||
{
|
||||
// unlit
|
||||
if (!GltfUnlitMaterial.TryCreateParam(parser, i, out param))
|
||||
|
|
@ -108,35 +109,42 @@ namespace VRM
|
|||
|
||||
foreach (var kv in param.TextureSlots)
|
||||
{
|
||||
yield return kv.Value;
|
||||
var key = new SubAssetKey(typeof(Texture2D), kv.Value.UnityObjectName);
|
||||
yield return (key, kv.Value);
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<TextureImportParam> EnumerateAllTexturesDistinct(GltfParser parser)
|
||||
public IEnumerable<(SubAssetKey, TextureImportParam)> EnumerateAllTexturesDistinct(GltfParser parser)
|
||||
{
|
||||
var used = new HashSet<string>();
|
||||
var used = new HashSet<SubAssetKey>();
|
||||
Func<(SubAssetKey, TextureImportParam), bool> add = (kv) =>
|
||||
{
|
||||
var (key, textureInfo) = kv;
|
||||
return used.Add(key);
|
||||
};
|
||||
|
||||
for (int i = 0; i < parser.GLTF.materials.Count; ++i)
|
||||
{
|
||||
var vrmMaterial = m_vrm.materialProperties[i];
|
||||
if (vrmMaterial.shader == MToon.Utils.ShaderName)
|
||||
{
|
||||
// MToon
|
||||
foreach (var textureInfo in EnumerateTexturesForMaterial(parser, i))
|
||||
foreach (var kv in EnumerateTexturesForMaterial(parser, i))
|
||||
{
|
||||
if (used.Add(textureInfo.ExtractKey))
|
||||
if (add(kv))
|
||||
{
|
||||
yield return textureInfo;
|
||||
yield return kv;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// PBR or Unlit
|
||||
foreach (var textureInfo in GltfTextureEnumerator.EnumerateTexturesForMaterial(parser, i))
|
||||
foreach (var kv in GltfTextureEnumerator.EnumerateTexturesForMaterial(parser, i))
|
||||
{
|
||||
if (used.Add(textureInfo.ExtractKey))
|
||||
if (add(kv))
|
||||
{
|
||||
yield return textureInfo;
|
||||
yield return kv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -145,10 +153,10 @@ namespace VRM
|
|||
// thumbnail
|
||||
if (m_vrm.meta != null && m_vrm.meta.texture != -1)
|
||||
{
|
||||
var textureInfo = GltfTextureImporter.CreateSRGB(parser, m_vrm.meta.texture, Vector2.zero, Vector2.one);
|
||||
if (used.Add(textureInfo.ExtractKey))
|
||||
var kv = GltfTextureImporter.CreateSRGB(parser, m_vrm.meta.texture, Vector2.zero, Vector2.one);
|
||||
if (add(kv))
|
||||
{
|
||||
yield return textureInfo;
|
||||
yield return kv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ namespace VRM
|
|||
textures = new List<glTFTexture>
|
||||
{
|
||||
new glTFTexture{
|
||||
name = "texture0",
|
||||
source = 0,
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -39,13 +39,13 @@ namespace UniVRM10
|
|||
}
|
||||
|
||||
// meta
|
||||
importer.DrawRemapGUI<VRM10MetaObject>(new string[] { VRM10MetaObject.ExtractKey });
|
||||
importer.DrawRemapGUI<VRM10MetaObject>(new SubAssetKey[] { VRM10MetaObject.SubAssetKey });
|
||||
|
||||
// expression avatar
|
||||
importer.DrawRemapGUI<VRM10ExpressionAvatar>(new string[] { VRM10ExpressionAvatar.ExtractKey });
|
||||
importer.DrawRemapGUI<VRM10ExpressionAvatar>(new SubAssetKey[] { VRM10ExpressionAvatar.SubAssetKey });
|
||||
|
||||
// expressions
|
||||
importer.DrawRemapGUI<VRM10Expression>(vrm.Expressions.Select(x => CreateKey(x).ExtractKey));
|
||||
importer.DrawRemapGUI<VRM10Expression>(vrm.Expressions.Select(x => CreateKey(x).SubAssetKey));
|
||||
|
||||
if (GUILayout.Button("Clear"))
|
||||
{
|
||||
|
|
@ -73,7 +73,7 @@ namespace UniVRM10
|
|||
|
||||
// meta
|
||||
{
|
||||
foreach (var asset in importer.GetSubAssets<VRM10MetaObject>(importer.assetPath))
|
||||
foreach (var (key, asset) in importer.GetSubAssets<VRM10MetaObject>(importer.assetPath))
|
||||
{
|
||||
asset.ExtractSubAsset($"{path}/{asset.name}.asset", false);
|
||||
}
|
||||
|
|
@ -81,13 +81,13 @@ namespace UniVRM10
|
|||
|
||||
{
|
||||
// expressions
|
||||
foreach (var asset in importer.GetSubAssets<VRM10Expression>(importer.assetPath))
|
||||
foreach (var (key, asset) in importer.GetSubAssets<VRM10Expression>(importer.assetPath))
|
||||
{
|
||||
asset.ExtractSubAsset($"{path}/{asset.name}.asset", false);
|
||||
}
|
||||
|
||||
// expressions
|
||||
foreach (var asset in importer.GetSubAssets<VRM10ExpressionAvatar>(importer.assetPath))
|
||||
foreach (var (key, asset) in importer.GetSubAssets<VRM10ExpressionAvatar>(importer.assetPath))
|
||||
{
|
||||
asset.ExtractSubAsset($"{path}/{asset.name}.asset", false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ namespace UniVRM10
|
|||
using (var loader = new RuntimeUnityBuilder(parser, externalObjectMap))
|
||||
{
|
||||
// settings TextureImporters
|
||||
foreach (var textureInfo in Vrm10MToonMaterialImporter.EnumerateAllTexturesDistinct(parser))
|
||||
foreach (var (key, textureInfo) in Vrm10MToonMaterialImporter.EnumerateAllTexturesDistinct(parser))
|
||||
{
|
||||
TextureImporterConfigurator.Configure(textureInfo, loader.TextureFactory.ExternalMap);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UniGLTF;
|
||||
|
||||
namespace UniVRM10
|
||||
{
|
||||
|
|
@ -173,11 +174,11 @@ namespace UniVRM10
|
|||
return 0;
|
||||
}
|
||||
|
||||
public string ExtractKey
|
||||
public SubAssetKey SubAssetKey
|
||||
{
|
||||
get
|
||||
{
|
||||
return $"Expression.{this}";
|
||||
return new SubAssetKey(typeof(VRM10Expression), this.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ namespace UniVRM10
|
|||
[CreateAssetMenu(menuName = "VRM10/ExpressionAvatar")]
|
||||
public sealed class VRM10ExpressionAvatar : ScriptableObject
|
||||
{
|
||||
public const string ExtractKey = "ExpressionAvatar";
|
||||
public static UniGLTF.SubAssetKey SubAssetKey => new UniGLTF.SubAssetKey(typeof(VRM10ExpressionAvatar), "ExpressionAvatar");
|
||||
|
||||
[SerializeField]
|
||||
public List<VRM10Expression> Clips = new List<VRM10Expression>();
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using MeshUtility;
|
||||
using UniGLTF;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
|
|
@ -10,7 +11,7 @@ namespace UniVRM10
|
|||
[CreateAssetMenu(menuName = "VRM10/MetaObject")]
|
||||
public class VRM10MetaObject : ScriptableObject
|
||||
{
|
||||
public const string ExtractKey = "Meta";
|
||||
public static SubAssetKey SubAssetKey => new SubAssetKey(typeof(VRM10MetaObject), "Meta");
|
||||
|
||||
[SerializeField]
|
||||
public string ExporterVersion;
|
||||
|
|
|
|||
|
|
@ -7,20 +7,6 @@ namespace UniVRM10
|
|||
{
|
||||
public static class ExpressionExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// for SubAssetName
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static string ExtractKey(this Expression expression)
|
||||
{
|
||||
ExpressionKey key =
|
||||
(expression.Preset == ExpressionPreset.custom)
|
||||
? ExpressionKey.CreateCustom(expression.Name)
|
||||
: ExpressionKey.CreateFromPreset(expression.Preset)
|
||||
;
|
||||
return key.ExtractKey;
|
||||
}
|
||||
|
||||
public static UniVRM10.MorphTargetBinding Build10(this MorphTargetBind bind, GameObject root, RuntimeUnityBuilder.ModelMap loader, VrmLib.Model model)
|
||||
{
|
||||
var libNode = model.Nodes[bind.Node.Value];
|
||||
|
|
|
|||
|
|
@ -245,7 +245,7 @@ namespace UniVRM10
|
|||
{
|
||||
var src = vrm.Meta;
|
||||
m_meta = ScriptableObject.CreateInstance<VRM10MetaObject>();
|
||||
m_meta.name = VRM10MetaObject.ExtractKey;
|
||||
m_meta.name = VRM10MetaObject.SubAssetKey.Name;
|
||||
controller.Meta = m_meta;
|
||||
m_meta.Name = src.Name;
|
||||
m_meta.Version = src.Version;
|
||||
|
|
@ -270,9 +270,9 @@ namespace UniVRM10
|
|||
{
|
||||
m_meta.Authors.AddRange(src.Authors);
|
||||
}
|
||||
if (Vrm10MToonMaterialImporter.TryGetMetaThumbnailTextureImportParam(Parser, vrm, out VRMShaders.TextureImportParam param))
|
||||
if (Vrm10MToonMaterialImporter.TryGetMetaThumbnailTextureImportParam(Parser, vrm, out (SubAssetKey, VRMShaders.TextureImportParam Param) kv))
|
||||
{
|
||||
var texture = await TextureFactory.GetTextureAsync(param);
|
||||
var texture = await TextureFactory.GetTextureAsync(kv.Param);
|
||||
if (texture != null)
|
||||
{
|
||||
m_meta.Thumbnail = texture;
|
||||
|
|
@ -286,14 +286,14 @@ namespace UniVRM10
|
|||
controller.Expression.ExpressionAvatar = ScriptableObject.CreateInstance<VRM10ExpressionAvatar>();
|
||||
|
||||
m_exressionAvatar = controller.Expression.ExpressionAvatar;
|
||||
m_exressionAvatar.name = VRM10ExpressionAvatar.ExtractKey;
|
||||
m_exressionAvatar.name = VRM10ExpressionAvatar.SubAssetKey.Name;
|
||||
|
||||
foreach (var expression in vrm.Expressions)
|
||||
{
|
||||
var clip = ScriptableObject.CreateInstance<UniVRM10.VRM10Expression>();
|
||||
clip.Preset = expression.Preset;
|
||||
clip.ExpressionName = expression.Name;
|
||||
clip.name = Key(expression).ExtractKey;
|
||||
clip.name = Key(expression).SubAssetKey.Name;
|
||||
clip.IsBinary = expression.IsBinary.GetValueOrDefault();
|
||||
clip.OverrideBlink = expression.OverrideBlink;
|
||||
clip.OverrideLookAt = expression.OverrideLookAt;
|
||||
|
|
|
|||
|
|
@ -128,7 +128,7 @@ namespace UniVRM10
|
|||
// base color
|
||||
if (m.pbrMetallicRoughness?.baseColorTexture != null)
|
||||
{
|
||||
param.TextureSlots.Add("_MainTex", GltfPBRMaterial.BaseColorTexture(parser, m));
|
||||
param.TextureSlots.Add("_MainTex", GltfPBRMaterial.BaseColorTexture(parser, m).Param);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -136,7 +136,7 @@ namespace UniVRM10
|
|||
{
|
||||
// normal map
|
||||
param.Actions.Add(material => material.EnableKeyword("_NORMALMAP"));
|
||||
var textureParam = GltfPBRMaterial.NormalTexture(parser, m);
|
||||
var textureParam = GltfPBRMaterial.NormalTexture(parser, m).Param;
|
||||
param.TextureSlots.Add("_BumpMap", textureParam);
|
||||
param.FloatValues.Add("_BumpScale", m.normalTexture.scale);
|
||||
}
|
||||
|
|
@ -144,34 +144,34 @@ namespace UniVRM10
|
|||
if (m.emissiveTexture != null && m.emissiveTexture.index != -1)
|
||||
{
|
||||
var (offset, scale) = GltfMaterialImporter.GetTextureOffsetAndScale(m.emissiveTexture);
|
||||
var textureParam = GltfTextureImporter.CreateSRGB(parser, m.emissiveTexture.index, offset, scale);
|
||||
var textureParam = GltfTextureImporter.CreateSRGB(parser, m.emissiveTexture.index, offset, scale).Param;
|
||||
param.TextureSlots.Add("_EmissionMap", textureParam);
|
||||
}
|
||||
|
||||
// TODO:
|
||||
if (mtoon.ShadeMultiplyTexture.HasValue)
|
||||
{
|
||||
var textureParam = GltfTextureImporter.CreateSRGB(parser, mtoon.ShadeMultiplyTexture.Value, Vector2.zero, Vector2.one);
|
||||
var textureParam = GltfTextureImporter.CreateSRGB(parser, mtoon.ShadeMultiplyTexture.Value, Vector2.zero, Vector2.one).Param;
|
||||
param.TextureSlots.Add("_ShadeTexture", textureParam);
|
||||
}
|
||||
if (mtoon.OutlineWidthMultiplyTexture.HasValue)
|
||||
{
|
||||
var textureParam = GltfTextureImporter.CreateSRGB(parser, mtoon.OutlineWidthMultiplyTexture.Value, Vector2.zero, Vector2.one);
|
||||
var textureParam = GltfTextureImporter.CreateSRGB(parser, mtoon.OutlineWidthMultiplyTexture.Value, Vector2.zero, Vector2.one).Param;
|
||||
param.TextureSlots.Add("_OutlineWidthTexture", textureParam);
|
||||
}
|
||||
if (mtoon.AdditiveTexture.HasValue)
|
||||
{
|
||||
var textureParam = GltfTextureImporter.CreateSRGB(parser, mtoon.AdditiveTexture.Value, Vector2.zero, Vector2.one);
|
||||
var textureParam = GltfTextureImporter.CreateSRGB(parser, mtoon.AdditiveTexture.Value, Vector2.zero, Vector2.one).Param;
|
||||
param.TextureSlots.Add("_SphereAdd", textureParam);
|
||||
}
|
||||
if (mtoon.RimMultiplyTexture.HasValue)
|
||||
{
|
||||
var textureParam = GltfTextureImporter.CreateSRGB(parser, mtoon.RimMultiplyTexture.Value, Vector2.zero, Vector2.one);
|
||||
var textureParam = GltfTextureImporter.CreateSRGB(parser, mtoon.RimMultiplyTexture.Value, Vector2.zero, Vector2.one).Param;
|
||||
param.TextureSlots.Add("_RimTexture", textureParam); ;
|
||||
}
|
||||
if (mtoon.UvAnimationMaskTexture.HasValue)
|
||||
{
|
||||
var textureParam = GltfTextureImporter.CreateSRGB(parser, mtoon.UvAnimationMaskTexture.Value, Vector2.zero, Vector2.one);
|
||||
var textureParam = GltfTextureImporter.CreateSRGB(parser, mtoon.UvAnimationMaskTexture.Value, Vector2.zero, Vector2.one).Param;
|
||||
param.TextureSlots.Add("_UvAnimMaskTexture", textureParam);
|
||||
}
|
||||
|
||||
|
|
@ -184,7 +184,7 @@ namespace UniVRM10
|
|||
/// <param name="parser"></param>
|
||||
/// <param name="m"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<TextureImportParam> EnumerateTexturesForMaterial(GltfParser parser, int i)
|
||||
public static IEnumerable<(SubAssetKey, TextureImportParam)> EnumerateTexturesForMaterial(GltfParser parser, int i)
|
||||
{
|
||||
// mtoon
|
||||
if (!TryCreateParam(parser, i, out MaterialImportParam param))
|
||||
|
|
@ -199,7 +199,8 @@ namespace UniVRM10
|
|||
|
||||
foreach (var kv in param.TextureSlots)
|
||||
{
|
||||
yield return kv.Value;
|
||||
var key = new SubAssetKey(typeof(Texture2D), kv.Key);
|
||||
yield return (key, kv.Value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -212,7 +213,7 @@ namespace UniVRM10
|
|||
/// <param name="vrm"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static bool TryGetMetaThumbnailTextureImportParam(GltfParser parser, UniGLTF.Extensions.VRMC_vrm.VRMC_vrm vrm, out TextureImportParam value)
|
||||
public static bool TryGetMetaThumbnailTextureImportParam(GltfParser parser, UniGLTF.Extensions.VRMC_vrm.VRMC_vrm vrm, out (SubAssetKey, TextureImportParam) value)
|
||||
{
|
||||
if (vrm?.Meta == null || !vrm.Meta.ThumbnailImage.HasValue)
|
||||
{
|
||||
|
|
@ -223,17 +224,19 @@ namespace UniVRM10
|
|||
// thumbnail
|
||||
var imageIndex = vrm.Meta.ThumbnailImage.Value;
|
||||
var gltfImage = parser.GLTF.images[imageIndex];
|
||||
var name = new TextureImportName(TextureImportTypes.sRGB, gltfImage.name, gltfImage.GetExt(), "");
|
||||
var name = TextureImportName.GetUnityObjectName(TextureImportTypes.sRGB, gltfImage.name, gltfImage.uri);
|
||||
|
||||
GetTextureBytesAsync getBytesAsync = () =>
|
||||
{
|
||||
var bytes = parser.GLTF.GetImageBytes(parser.Storage, imageIndex);
|
||||
return Task.FromResult(GltfTextureImporter.ToArray(bytes));
|
||||
};
|
||||
value = new TextureImportParam(name, Vector2.zero, Vector2.one, default, TextureImportTypes.sRGB, default, default,
|
||||
var param = new TextureImportParam(name, gltfImage.GetExt(), gltfImage.uri, Vector2.zero, Vector2.one, default, TextureImportTypes.sRGB, default, default,
|
||||
getBytesAsync, default, default,
|
||||
default, default, default
|
||||
);
|
||||
var key = new SubAssetKey(typeof(Texture2D), name);
|
||||
value = (key, param);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -242,26 +245,31 @@ namespace UniVRM10
|
|||
/// </summary>
|
||||
/// <param name="parser"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<TextureImportParam> EnumerateAllTexturesDistinct(GltfParser parser)
|
||||
public static IEnumerable<(SubAssetKey, TextureImportParam)> EnumerateAllTexturesDistinct(GltfParser parser)
|
||||
{
|
||||
if (!UniGLTF.Extensions.VRMC_vrm.GltfDeserializer.TryGet(parser.GLTF.extensions, out UniGLTF.Extensions.VRMC_vrm.VRMC_vrm vrm))
|
||||
{
|
||||
throw new System.Exception("not vrm");
|
||||
}
|
||||
|
||||
if (TryGetMetaThumbnailTextureImportParam(parser, vrm, out TextureImportParam thumbnail))
|
||||
if (TryGetMetaThumbnailTextureImportParam(parser, vrm, out (SubAssetKey, TextureImportParam) thumbnail))
|
||||
{
|
||||
yield return thumbnail;
|
||||
}
|
||||
|
||||
var used = new HashSet<string>();
|
||||
var used = new HashSet<SubAssetKey>();
|
||||
Func<(SubAssetKey, TextureImportParam), bool> add = (kv) =>
|
||||
{
|
||||
var (key, textureInfo) = kv;
|
||||
return used.Add(key);
|
||||
};
|
||||
for (int i = 0; i < parser.GLTF.materials.Count; ++i)
|
||||
{
|
||||
foreach (var textureInfo in EnumerateTexturesForMaterial(parser, i))
|
||||
foreach (var kv in EnumerateTexturesForMaterial(parser, i))
|
||||
{
|
||||
if (used.Add(textureInfo.ExtractKey))
|
||||
if (add(kv))
|
||||
{
|
||||
yield return textureInfo;
|
||||
yield return kv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -118,9 +118,8 @@ namespace VRMShaders
|
|||
public IEnumerable<TextureLoadInfo> Textures => m_textureCache.Values;
|
||||
|
||||
|
||||
async Task<TextureLoadInfo> GetOrCreateBaseTexture(TextureImportParam param, GetTextureBytesAsync getTextureBytesAsync, RenderTextureReadWrite colorSpace, bool used)
|
||||
async Task<TextureLoadInfo> GetOrCreateBaseTexture(string name, TextureImportParam param, GetTextureBytesAsync getTextureBytesAsync, RenderTextureReadWrite colorSpace, bool used)
|
||||
{
|
||||
var name = param.GltfName;
|
||||
if (m_textureCache.TryGetValue(name, out TextureLoadInfo cacheInfo))
|
||||
{
|
||||
return cacheInfo;
|
||||
|
|
@ -194,17 +193,9 @@ namespace VRMShaders
|
|||
/// <returns></returns>
|
||||
public async Task<Texture2D> GetTextureAsync(TextureImportParam param)
|
||||
{
|
||||
//
|
||||
// ExtractKey で External とのマッチングを試みる
|
||||
//
|
||||
// Normal => GltfName
|
||||
// Standard => ConvertedName
|
||||
// sRGB => GltfName
|
||||
// Linear => GltfName
|
||||
//
|
||||
if (param.Index0 != null && ExternalMap != null)
|
||||
{
|
||||
if (ExternalMap.TryGetValue(param.ExtractKey, out Texture2D external))
|
||||
if (ExternalMap.TryGetValue(param.UnityObjectName, out Texture2D external))
|
||||
{
|
||||
return external;
|
||||
}
|
||||
|
|
@ -215,11 +206,11 @@ namespace VRMShaders
|
|||
case TextureImportTypes.NormalMap:
|
||||
// Runtime/SubAsset 用に変換する
|
||||
{
|
||||
if (!m_textureCache.TryGetValue(param.ConvertedName, out TextureLoadInfo info))
|
||||
if (!m_textureCache.TryGetValue(param.UnityObjectName, out TextureLoadInfo info))
|
||||
{
|
||||
var baseTexture = await GetOrCreateBaseTexture(param, param.Index0, RenderTextureReadWrite.Linear, false);
|
||||
var baseTexture = await GetOrCreateBaseTexture($"{param.UnityObjectName}.normal_base", param, param.Index0, RenderTextureReadWrite.Linear, false);
|
||||
var converted = NormalConverter.Import(baseTexture.Texture);
|
||||
converted.name = param.ConvertedName;
|
||||
converted.name = param.UnityObjectName;
|
||||
info = new TextureLoadInfo(converted, true, false);
|
||||
m_textureCache.Add(converted.name, info);
|
||||
}
|
||||
|
|
@ -229,20 +220,20 @@ namespace VRMShaders
|
|||
case TextureImportTypes.StandardMap:
|
||||
// 変換する
|
||||
{
|
||||
if (!m_textureCache.TryGetValue(param.ConvertedName, out TextureLoadInfo info))
|
||||
if (!m_textureCache.TryGetValue(param.UnityObjectName, out TextureLoadInfo info))
|
||||
{
|
||||
TextureLoadInfo baseTexture = default;
|
||||
if (param.Index0 != null)
|
||||
{
|
||||
baseTexture = await GetOrCreateBaseTexture(param, param.Index0, RenderTextureReadWrite.Linear, false);
|
||||
baseTexture = await GetOrCreateBaseTexture($"{param.UnityObjectName}.metallicRoughness", param, param.Index0, RenderTextureReadWrite.Linear, false);
|
||||
}
|
||||
TextureLoadInfo occlusionBaseTexture = default;
|
||||
if (param.Index1 != null)
|
||||
{
|
||||
occlusionBaseTexture = await GetOrCreateBaseTexture(param, param.Index1, RenderTextureReadWrite.Linear, false);
|
||||
occlusionBaseTexture = await GetOrCreateBaseTexture($"{param.UnityObjectName}.occlusion", param, param.Index1, RenderTextureReadWrite.Linear, false);
|
||||
}
|
||||
var converted = OcclusionMetallicRoughnessConverter.Import(baseTexture.Texture, param.MetallicFactor, param.RoughnessFactor, occlusionBaseTexture.Texture);
|
||||
converted.name = param.ConvertedName;
|
||||
converted.name = param.UnityObjectName;
|
||||
info = new TextureLoadInfo(converted, true, false);
|
||||
m_textureCache.Add(converted.name, info);
|
||||
}
|
||||
|
|
@ -251,14 +242,12 @@ namespace VRMShaders
|
|||
|
||||
default:
|
||||
{
|
||||
var baseTexture = await GetOrCreateBaseTexture(param, param.Index0, RenderTextureReadWrite.sRGB, true);
|
||||
var baseTexture = await GetOrCreateBaseTexture(param.UnityObjectName, param, param.Index0, RenderTextureReadWrite.sRGB, true);
|
||||
return baseTexture.Texture;
|
||||
}
|
||||
}
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,26 +1,20 @@
|
|||
using System.IO;
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace VRMShaders
|
||||
{
|
||||
public struct TextureImportName
|
||||
public static class TextureImportName
|
||||
{
|
||||
public readonly string GltfName;
|
||||
public readonly string ConvertedName;
|
||||
|
||||
public readonly string Ext;
|
||||
public readonly string Uri;
|
||||
public readonly string ExtractKey;
|
||||
|
||||
public static string GetExtractKey(TextureImportTypes type, string gltfName, string convertedName, string uri)
|
||||
public static string GetUnityObjectName(TextureImportTypes type, string gltfName, string uri)
|
||||
{
|
||||
if (type == TextureImportTypes.StandardMap)
|
||||
{
|
||||
// metallic, smooth, occlusion
|
||||
return convertedName;
|
||||
return $"{gltfName}{STANDARD_SUFFIX}";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!string.IsNullOrEmpty(uri))
|
||||
if (!string.IsNullOrEmpty(uri) && !uri.StartsWith("data:", StringComparison.Ordinal))
|
||||
{
|
||||
// external image
|
||||
return Path.GetFileNameWithoutExtension(uri);
|
||||
|
|
@ -33,30 +27,9 @@ namespace VRMShaders
|
|||
}
|
||||
}
|
||||
|
||||
public TextureImportName(TextureImportTypes textureType, string gltfName, string ext, string uri)
|
||||
{
|
||||
GltfName = gltfName;
|
||||
ConvertedName = TextureImportName.Convert(gltfName, textureType);
|
||||
Ext = ext;
|
||||
Uri = uri;
|
||||
ExtractKey = GetExtractKey(textureType, gltfName, ConvertedName, uri);
|
||||
}
|
||||
|
||||
public string GltfFileName => $"{GltfName}{Ext}";
|
||||
|
||||
public string ConvertedFileName => $"{ConvertedName}.png";
|
||||
|
||||
public const string NORMAL_SUFFIX = ".normal";
|
||||
public const string STANDARD_SUFFIX = ".standard";
|
||||
public static string Convert(string name, TextureImportTypes textureType)
|
||||
{
|
||||
switch (textureType)
|
||||
{
|
||||
case TextureImportTypes.StandardMap: return $"{name}{STANDARD_SUFFIX}";
|
||||
case TextureImportTypes.NormalMap: return $"{name}{NORMAL_SUFFIX}";
|
||||
default: return name;
|
||||
}
|
||||
}
|
||||
|
||||
public static string RemoveSuffix(string src)
|
||||
{
|
||||
if (src.EndsWith(NORMAL_SUFFIX))
|
||||
|
|
|
|||
|
|
@ -22,17 +22,10 @@ namespace VRMShaders
|
|||
public const string METALLIC_GLOSS_PROP = "_MetallicGlossMap";
|
||||
public const string OCCLUSION_PROP = "_OcclusionMap";
|
||||
|
||||
|
||||
public readonly TextureImportName Name;
|
||||
public string GltfName => Name.GltfName;
|
||||
public string GltfFileName => Name.GltfFileName;
|
||||
public string ConvertedName => Name.ConvertedName;
|
||||
public string ConvertedFileName => Name.ConvertedFileName;
|
||||
public string Uri => Name.Uri;
|
||||
public readonly string UnityObjectName;
|
||||
public readonly string Ext;
|
||||
public readonly string Uri;
|
||||
|
||||
public string ExtractKey => Name.ExtractKey;
|
||||
|
||||
|
||||
public Vector2 Offset;
|
||||
public Vector2 Scale;
|
||||
|
||||
|
|
@ -41,7 +34,7 @@ namespace VRMShaders
|
|||
public readonly TextureImportTypes TextureType;
|
||||
public readonly float MetallicFactor;
|
||||
public readonly float RoughnessFactor;
|
||||
|
||||
|
||||
public readonly GetTextureBytesAsync Index0;
|
||||
public readonly GetTextureBytesAsync Index1;
|
||||
public readonly GetTextureBytesAsync Index2;
|
||||
|
|
@ -54,7 +47,7 @@ namespace VRMShaders
|
|||
/// </summary>
|
||||
public bool ExtractConverted => TextureType == TextureImportTypes.StandardMap;
|
||||
|
||||
public TextureImportParam(TextureImportName name, Vector2 offset, Vector2 scale, SamplerParam sampler, TextureImportTypes textureType, float metallicFactor, float roughnessFactor,
|
||||
public TextureImportParam(string name, string ext, string uri, Vector2 offset, Vector2 scale, SamplerParam sampler, TextureImportTypes textureType, float metallicFactor, float roughnessFactor,
|
||||
GetTextureBytesAsync i0,
|
||||
GetTextureBytesAsync i1,
|
||||
GetTextureBytesAsync i2,
|
||||
|
|
@ -62,7 +55,9 @@ namespace VRMShaders
|
|||
GetTextureBytesAsync i4,
|
||||
GetTextureBytesAsync i5)
|
||||
{
|
||||
Name = name;
|
||||
UnityObjectName = name;
|
||||
Ext = ext;
|
||||
Uri = uri;
|
||||
Offset = offset;
|
||||
Scale = scale;
|
||||
Sampler = sampler;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user