Merge pull request #837 from ousttrue/feature10/update_vrm1_loader

vrm1のローダー更新
This commit is contained in:
PoChang007
2021-04-02 13:11:06 +09:00
committed by GitHub
286 changed files with 3617 additions and 12782 deletions

View File

@@ -34,14 +34,14 @@ namespace UniGLTF
static bool s_foldMaterials = true;
static bool s_foldTextures = true;
public static void OnGUIMaterial(ScriptedImporter importer, GltfParser parser)
public static void OnGUIMaterial(ScriptedImporter importer, GltfParser parser, EnumerateAllTexturesDistinctFunc enumTextures)
{
var canExtract = !importer.GetExternalObjectMap().Any(x => x.Value is Material || x.Value is Texture2D);
using (new TmpGuiEnable(canExtract))
{
if (GUILayout.Button("Extract Materials And Textures ..."))
{
ExtractMaterialsAndTextures(importer, parser);
ExtractMaterialsAndTextures(importer, parser, enumTextures);
}
}
@@ -57,7 +57,7 @@ namespace UniGLTF
s_foldTextures = EditorGUILayout.Foldout(s_foldTextures, "Remapped Textures");
if (s_foldTextures)
{
var names = GltfTextureEnumerator.Enumerate(parser)
var names = enumTextures(parser)
.Select(x =>
{
if (x.TextureType != TextureImportTypes.StandardMap && !string.IsNullOrEmpty(x.Uri))
@@ -122,7 +122,7 @@ namespace UniGLTF
AssetDatabase.ImportAsset(self.assetPath, ImportAssetOptions.ForceUpdate);
}
static void ExtractMaterialsAndTextures(ScriptedImporter self, GltfParser parser)
static void ExtractMaterialsAndTextures(ScriptedImporter self, GltfParser parser, EnumerateAllTexturesDistinctFunc enumTextures)
{
if (string.IsNullOrEmpty(self.assetPath))
{
@@ -143,7 +143,7 @@ namespace UniGLTF
var assetPath = UnityPath.FromFullpath(parser.TargetPath);
var dirName = $"{assetPath.FileNameWithoutExtension}.Textures";
TextureExtractor.ExtractTextures(parser, assetPath.Parent.Child(dirName),
GltfTextureEnumerator.Enumerate,
enumTextures,
self.GetSubAssets<UnityEngine.Texture2D>(self.assetPath).ToArray(),
addRemap,
onCompleted

View File

@@ -48,7 +48,7 @@ namespace UniGLTF
break;
case Tabs.Materials:
EditorMaterial.OnGUIMaterial(m_importer, m_parser);
EditorMaterial.OnGUIMaterial(m_importer, m_parser, GltfTextureEnumerator.EnumerateAllTexturesDistinct);
break;
}
}

View File

@@ -48,7 +48,7 @@ namespace UniGLTF
break;
case Tabs.Materials:
EditorMaterial.OnGUIMaterial(m_importer, m_parser);
EditorMaterial.OnGUIMaterial(m_importer, m_parser, GltfTextureEnumerator.EnumerateAllTexturesDistinct);
break;
}
}

View File

@@ -1,4 +1,3 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
@@ -37,32 +36,28 @@ namespace UniGLTF
// Import(create unity objects)
//
var externalObjectMap = scriptedImporter.GetExternalObjectMap().Select(kv => (kv.Value.name, kv.Value)).ToArray();
var externalTextures = EnumerateTexturesFromUri(externalObjectMap, parser, UnityPath.FromUnityPath(scriptedImporter.assetPath).Parent).ToArray();
using (var loaded = new ImporterContext(parser, externalObjectMap.Concat(externalTextures)))
using (var loader = new ImporterContext(parser, externalObjectMap.Concat(externalTextures)))
{
// settings TextureImporters
foreach (var textureInfo in GltfTextureEnumerator.Enumerate(parser))
foreach (var textureInfo in GltfTextureEnumerator.EnumerateAllTexturesDistinct(parser))
{
TextureImporterConfigurator.Configure(textureInfo, loaded.TextureFactory.ExternalMap);
TextureImporterConfigurator.Configure(textureInfo, loader.TextureFactory.ExternalMap);
}
loaded.InvertAxis = reverseAxis;
loaded.Load();
loaded.ShowMeshes();
loader.InvertAxis = reverseAxis;
loader.Load();
loader.ShowMeshes();
loaded.TransferOwnership(o =>
loader.TransferOwnership(o =>
{
#if VRM_DEVELOP
Debug.Log($"[{o.GetType().Name}] {o.name} will not destroy");
#endif
context.AddObjectToAsset(o.name, o);
if (o is GameObject)
{
// Root GameObject is main object
context.SetMainObject(loaded.Root);
context.SetMainObject(loader.Root);
}
return true;
@@ -74,7 +69,7 @@ namespace UniGLTF
GltfParser parser, UnityPath dir)
{
var used = new HashSet<Texture2D>();
foreach (var texParam in GltfTextureEnumerator.Enumerate(parser))
foreach (var texParam in GltfTextureEnumerator.EnumerateAllTexturesDistinct(parser))
{
switch (texParam.TextureType)
{
@@ -96,8 +91,10 @@ namespace UniGLTF
{
// exclude. skip
}
else{
if(used.Add(asset)){
else
{
if (used.Add(asset))
{
yield return (asset.name, asset);
}
}

View File

@@ -102,7 +102,7 @@ namespace UniGLTF
/// <param name="dirName"></param>
/// <param name="onCompleted"></param>
public static void ExtractTextures(GltfParser parser, UnityPath textureDirectory,
TextureEnumerator textureEnumerator, Texture2D[] subAssets, Action<Texture2D> addRemap,
EnumerateAllTexturesDistinctFunc textureEnumerator, Texture2D[] subAssets, Action<Texture2D> addRemap,
Action<IEnumerable<UnityPath>> onCompleted = null)
{
var extractor = new TextureExtractor(parser, textureDirectory, subAssets);

View File

@@ -476,5 +476,51 @@ namespace UniGLTF
self.RemoveUnusedExtensions(json);
return (json, self.buffers);
}
public static bool IsGeneratedUniGLTFAndOlderThan(string generatorVersion, int major, int minor)
{
if (string.IsNullOrEmpty(generatorVersion)) return false;
if (generatorVersion == "UniGLTF") return true;
if (!generatorVersion.FastStartsWith("UniGLTF-")) return false;
try
{
var splitted = generatorVersion.Substring(8).Split('.');
var generatorMajor = int.Parse(splitted[0]);
var generatorMinor = int.Parse(splitted[1]);
if (generatorMajor < major)
{
return true;
}
else if (generatorMajor > major)
{
return false;
}
else
{
if (generatorMinor >= minor)
{
return false;
}
else
{
return true;
}
}
}
catch (Exception ex)
{
Debug.LogWarningFormat("{0}: {1}", generatorVersion, ex);
return false;
}
}
public static bool IsGeneratedUniGLTFAndOlder(this glTF gltf, int major, int minor)
{
if (gltf == null) return false;
if (gltf.asset == null) return false;
return IsGeneratedUniGLTFAndOlderThan(gltf.asset.generator, major, minor);
}
}
}

View File

@@ -1,5 +1,4 @@
using System;
using System.IO;
namespace UniGLTF
@@ -27,9 +26,11 @@ namespace UniGLTF
throw new NotImplementedException();
}
public ArraySegment<byte> GetBytes()
public void ExtendCapacity(int capacity)
{
return m_bytes;
throw new NotImplementedException();
}
public ArraySegment<byte> Bytes => m_bytes;
}
}

View File

@@ -5,7 +5,8 @@ namespace UniGLTF
public interface IBytesBuffer
{
string Uri { get; }
ArraySegment<Byte> GetBytes();
glTFBufferView Extend<T>(ArraySegment<T> array, glBufferTarget target) where T : struct;
ArraySegment<Byte> Bytes { get; }
glTFBufferView Extend<T>(ArraySegment<T> array, glBufferTarget target = glBufferTarget.NONE) where T : struct;
void ExtendCapacity(int capacity);
}
}

View File

@@ -6,11 +6,12 @@ namespace UniGLTF
[Serializable]
public class glTFBuffer
{
IBytesBuffer Storage;
IBytesBuffer m_buffer;
public IBytesBuffer Buffer => m_buffer;
public void OpenStorage(IStorage storage)
{
Storage = new ArraySegmentByteBuffer(storage.Get(uri));
m_buffer = new ArraySegmentByteBuffer(storage.Get(uri));
}
public glTFBuffer()
@@ -20,7 +21,7 @@ namespace UniGLTF
public glTFBuffer(IBytesBuffer storage)
{
Storage = storage;
m_buffer = storage;
}
public string uri;
@@ -39,14 +40,14 @@ namespace UniGLTF
}
public glTFBufferView Append<T>(ArraySegment<T> segment, glBufferTarget target) where T : struct
{
var view = Storage.Extend(segment, target);
byteLength = Storage.GetBytes().Count;
var view = m_buffer.Extend(segment, target);
byteLength = m_buffer.Bytes.Count;
return view;
}
public ArraySegment<Byte> GetBytes()
{
return Storage.GetBytes();
return m_buffer.Bytes;
}
}

View File

@@ -0,0 +1,98 @@
using System;
using System.Runtime.InteropServices;
namespace UniGLTF
{
/// <summary>
/// for exporter
/// </summary>
public class ArrayByteBuffer : IBytesBuffer
{
public string Uri
{
get;
private set;
}
Byte[] m_bytes;
int m_used;
public ArrayByteBuffer(Byte[] bytes = null)
{
Uri = "";
m_bytes = bytes;
}
public glTFBufferView Extend<T>(ArraySegment<T> array, glBufferTarget target) where T : struct
{
using (var pin = Pin.Create(array))
{
var elementSize = Marshal.SizeOf(typeof(T));
var view = Extend(pin.Ptr, array.Count * elementSize, elementSize, target);
return view;
}
}
public glTFBufferView Extend(IntPtr p, int bytesLength, int stride, glBufferTarget target)
{
var tmp = m_bytes;
// alignment
var padding = m_used % stride == 0 ? 0 : stride - m_used % stride;
if (m_bytes == null || m_used + padding + bytesLength > m_bytes.Length)
{
// recreate buffer
m_bytes = new Byte[m_used + padding + bytesLength];
if (m_used > 0)
{
Buffer.BlockCopy(tmp, 0, m_bytes, 0, m_used);
}
}
if (m_used + padding + bytesLength > m_bytes.Length)
{
throw new ArgumentOutOfRangeException();
}
Marshal.Copy(p, m_bytes, m_used + padding, bytesLength);
var result = new glTFBufferView
{
buffer = 0,
byteLength = bytesLength,
byteOffset = m_used + padding,
byteStride = stride,
target = target,
};
m_used = m_used + padding + bytesLength;
return result;
}
public void ExtendCapacity(int capacity)
{
if (m_bytes != null && capacity < m_bytes.Length)
{
return;
}
var newBuffer = new byte[capacity];
if (m_bytes != null && m_used > 0)
{
Buffer.BlockCopy(m_bytes, 0, newBuffer, 0, m_used);
}
m_bytes = newBuffer;
}
public ArraySegment<byte> Bytes
{
get
{
if (m_bytes == null)
{
return new ArraySegment<byte>();
}
return new ArraySegment<byte>(m_bytes, 0, m_used);
}
}
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: d9b840dcce2a5b94aae00d4bc4bf7e10
guid: d095d4c4eb5e68f4bb10c21bb3604cdb
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -1,158 +0,0 @@
using System;
using System.IO;
using System.Runtime.InteropServices;
namespace UniGLTF
{
public static class IBytesBufferExtensions
{
public static glTFBufferView Extend<T>(this IBytesBuffer buffer, T[] array, glBufferTarget target) where T : struct
{
return buffer.Extend(new ArraySegment<T>(array), target);
}
}
/// <summary>
/// for buffer with uri read
/// </summary>
public class UriByteBuffer : IBytesBuffer
{
public string Uri
{
get;
private set;
}
Byte[] m_bytes;
public ArraySegment<byte> GetBytes()
{
return new ArraySegment<byte>(m_bytes);
}
public UriByteBuffer(string baseDir, string uri)
{
Uri = uri;
m_bytes = ReadFromUri(baseDir, uri);
}
const string DataPrefix = "data:application/octet-stream;base64,";
const string DataPrefix2 = "data:application/gltf-buffer;base64,";
const string DataPrefix3 = "data:image/jpeg;base64,";
[Obsolete("Use ReadEmbedded(uri)")]
public static Byte[] ReadEmbeded(string uri)
{
return ReadEmbedded(uri);
}
public static Byte[] ReadEmbedded(string uri)
{
var pos = uri.IndexOf(";base64,");
if (pos < 0)
{
throw new NotImplementedException();
}
else
{
return Convert.FromBase64String(uri.Substring(pos + 8));
}
}
Byte[] ReadFromUri(string baseDir, string uri)
{
var bytes = ReadEmbedded(uri);
if (bytes != null)
{
return bytes;
}
else
{
// as local file path
return File.ReadAllBytes(Path.Combine(baseDir, uri));
}
}
public glTFBufferView Extend<T>(ArraySegment<T> array, glBufferTarget target) where T : struct
{
throw new NotImplementedException();
}
}
/// <summary>
/// for exporter
/// </summary>
public class ArrayByteBuffer : IBytesBuffer
{
public string Uri
{
get;
private set;
}
Byte[] m_bytes;
int m_used;
public ArrayByteBuffer(Byte[] bytes = null)
{
Uri = "";
m_bytes = bytes;
}
public glTFBufferView Extend<T>(ArraySegment<T> array, glBufferTarget target) where T : struct
{
using (var pin = Pin.Create(array))
{
var elementSize = Marshal.SizeOf(typeof(T));
var view = Extend(pin.Ptr, array.Count * elementSize, elementSize, target);
return view;
}
}
public glTFBufferView Extend(IntPtr p, int bytesLength, int stride, glBufferTarget target)
{
var tmp = m_bytes;
// alignment
var padding = m_used % stride == 0 ? 0 : stride - m_used % stride;
if (m_bytes == null || m_used + padding + bytesLength > m_bytes.Length)
{
// recreate buffer
m_bytes = new Byte[m_used + padding + bytesLength];
if (m_used > 0)
{
Buffer.BlockCopy(tmp, 0, m_bytes, 0, m_used);
}
}
if (m_used + padding + bytesLength > m_bytes.Length)
{
throw new ArgumentOutOfRangeException();
}
Marshal.Copy(p, m_bytes, m_used + padding, bytesLength);
var result=new glTFBufferView
{
buffer = 0,
byteLength = bytesLength,
byteOffset = m_used + padding,
byteStride = stride,
target = target,
};
m_used = m_used + padding + bytesLength;
return result;
}
public ArraySegment<byte> GetBytes()
{
if (m_bytes == null)
{
return new ArraySegment<byte>();
}
return new ArraySegment<byte>(m_bytes, 0, m_used);
}
}
}

View File

@@ -25,51 +25,6 @@ namespace UniGLTF
/// </summary>
public IStorage Storage;
public static bool IsGeneratedUniGLTFAndOlderThan(string generatorVersion, int major, int minor)
{
if (string.IsNullOrEmpty(generatorVersion)) return false;
if (generatorVersion == "UniGLTF") return true;
if (!generatorVersion.FastStartsWith("UniGLTF-")) return false;
try
{
var splitted = generatorVersion.Substring(8).Split('.');
var generatorMajor = int.Parse(splitted[0]);
var generatorMinor = int.Parse(splitted[1]);
if (generatorMajor < major)
{
return true;
}
else if (generatorMajor > major)
{
return false;
}
else
{
if (generatorMinor >= minor)
{
return false;
}
else
{
return true;
}
}
}
catch (Exception ex)
{
Debug.LogWarningFormat("{0}: {1}", generatorVersion, ex);
return false;
}
}
public bool IsGeneratedUniGLTFAndOlder(int major, int minor)
{
if (GLTF == null) return false;
if (GLTF.asset == null) return false;
return IsGeneratedUniGLTFAndOlderThan(GLTF.asset.generator, major, minor);
}
#region Parse
public void ParsePath(string path)

View File

@@ -1,7 +1,10 @@
namespace UniGLTF
using System.Collections.Generic;
using UnityEngine;
namespace UniGLTF
{
public interface IAnimationImporter
{
void Import(ImporterContext context);
List<AnimationClip> Import(glTF gltf, GameObject root, Axises invertAxis);
}
}
}

View File

@@ -3,9 +3,9 @@ using System.Linq;
using System.Collections.Generic;
using UnityEngine;
using System.Threading.Tasks;
using System.Text;
using VRMShaders;
namespace UniGLTF
{
/// <summary>
@@ -41,8 +41,6 @@ namespace UniGLTF
TextureFactory m_textureFactory;
public TextureFactory TextureFactory => m_textureFactory;
IAwaitCaller m_awaitCaller;
public ImporterContext(GltfParser parser,
IEnumerable<(string, UnityEngine.Object)> externalObjectMap = null)
{
@@ -81,20 +79,12 @@ namespace UniGLTF
{
awaitCaller = new TaskCaller();
}
m_awaitCaller = awaitCaller;
if (MeasureTime == null)
{
MeasureTime = new ImporterContextSpeedLog().MeasureTime;
}
var inverter = InvertAxis.Create();
if (Root == null)
{
Root = new GameObject("GLTF");
}
if (GLTF.extensionsRequired != null)
{
var sb = new List<string>();
@@ -116,14 +106,28 @@ namespace UniGLTF
await LoadMaterialsAsync();
}
await LoadGeometryAsync(awaitCaller, MeasureTime);
using (MeasureTime("AnimationImporter"))
{
AnimationClips.AddRange(AnimationImporter.Import(GLTF, Root, InvertAxis));
}
await OnLoadHierarchy(awaitCaller, MeasureTime);
}
protected virtual async Task LoadGeometryAsync(IAwaitCaller awaitCaller, Func<string, IDisposable> MeasureTime)
{
var inverter = InvertAxis.Create();
var meshImporter = new MeshImporter();
for (int i = 0; i < GLTF.meshes.Count; ++i)
{
var index = i;
using (MeasureTime("ReadMesh"))
{
var x = meshImporter.ReadMesh(this, index, inverter);
var y = await BuildMeshAsync(MeasureTime, x, index);
var x = meshImporter.ReadMesh(GLTF, index, inverter);
var y = await BuildMeshAsync(awaitCaller, MeasureTime, x, index);
Meshes.Add(y);
}
}
@@ -135,14 +139,14 @@ namespace UniGLTF
Nodes.Add(NodeImporter.ImportNode(GLTF.nodes[i], i).transform);
}
}
await m_awaitCaller.NextFrame();
await awaitCaller.NextFrame();
using (MeasureTime("BuildHierarchy"))
{
var nodes = new List<NodeImporter.TransformWithSkin>();
for (int i = 0; i < Nodes.Count; ++i)
{
nodes.Add(NodeImporter.BuildHierarchy(this, i));
nodes.Add(NodeImporter.BuildHierarchy(GLTF, i, Nodes, Meshes));
}
NodeImporter.FixCoordinate(this, nodes, inverter);
@@ -153,6 +157,10 @@ namespace UniGLTF
NodeImporter.SetupSkinning(this, nodes, i, inverter);
}
if (Root == null)
{
Root = new GameObject("GLTF");
}
if (GLTF.rootnodes != null)
{
// connect root
@@ -163,14 +171,7 @@ namespace UniGLTF
}
}
}
await m_awaitCaller.NextFrame();
using (MeasureTime("AnimationImporter"))
{
AnimationImporter.Import(this);
}
await OnLoadModel(m_awaitCaller, MeasureTime);
await awaitCaller.NextFrame();
}
public async Task LoadMaterialsAsync()
@@ -191,17 +192,17 @@ namespace UniGLTF
}
}
protected virtual Task OnLoadModel(IAwaitCaller awaitCaller, Func<string, IDisposable> MeasureTime)
protected virtual Task OnLoadHierarchy(IAwaitCaller awaitCaller, Func<string, IDisposable> MeasureTime)
{
// do nothing
return Task.FromResult<object>(null);
}
async Task<MeshWithMaterials> BuildMeshAsync(Func<string, IDisposable> MeasureTime, MeshImporter.MeshContext x, int i)
async Task<MeshWithMaterials> BuildMeshAsync(IAwaitCaller awaitCaller, Func<string, IDisposable> MeasureTime, MeshImporter.MeshContext x, int i)
{
using (MeasureTime("BuildMesh"))
{
var meshWithMaterials = await MeshImporter.BuildMeshAsync(m_awaitCaller, MaterialFactory, x);
var meshWithMaterials = await MeshImporter.BuildMeshAsync(awaitCaller, MaterialFactory, x);
var mesh = meshWithMaterials.Mesh;
// mesh name

View File

@@ -4,7 +4,7 @@ using VRMShaders;
namespace UniGLTF
{
public delegate IEnumerable<TextureImportParam> TextureEnumerator(GltfParser parser);
public delegate IEnumerable<TextureImportParam> EnumerateAllTexturesDistinctFunc(GltfParser parser);
/// <summary>
/// Texture 生成に関して
@@ -34,8 +34,10 @@ namespace UniGLTF
/// </summary>
public static class GltfTextureEnumerator
{
public static IEnumerable<TextureImportParam> EnumerateTextures(GltfParser parser, glTFMaterial m)
public static IEnumerable<TextureImportParam> EnumerateTexturesForMaterial(GltfParser parser, int i)
{
var m = parser.GLTF.materials[i];
int? metallicRoughnessTexture = default;
if (m.pbrMetallicRoughness != null)
{
@@ -79,14 +81,20 @@ namespace UniGLTF
}
}
public static IEnumerable<TextureImportParam> Enumerate(GltfParser parser)
/// <summary>
/// glTF 全体で使うテクスチャーをユニークになるように列挙する
/// </summary>
/// <param name="parser"></param>
/// <returns></returns>
public static IEnumerable<TextureImportParam> EnumerateAllTexturesDistinct(GltfParser parser)
{
var used = new HashSet<string>();
foreach (var material in parser.GLTF.materials)
for (int i = 0; i < parser.GLTF.materials.Count; ++i)
{
foreach (var textureInfo in EnumerateTextures(parser, material))
foreach (var textureInfo in EnumerateTexturesForMaterial(parser, i))
{
if(used.Add(textureInfo.ExtractKey)){
if (used.Add(textureInfo.ExtractKey))
{
yield return textureInfo;
}
}

View File

@@ -124,7 +124,7 @@ namespace UniGLTF
/// <param name="ctx"></param>
/// <param name="gltfMesh"></param>
/// <returns></returns>
public void ImportMeshIndependentVertexBuffer(ImporterContext ctx, glTFMesh gltfMesh, IAxisInverter inverter)
public void ImportMeshIndependentVertexBuffer(glTF gltf, glTFMesh gltfMesh, IAxisInverter inverter)
{
foreach (var prim in gltfMesh.primitives)
{
@@ -132,14 +132,14 @@ namespace UniGLTF
var indexBuffer = prim.indices;
// position は必ずある
var positions = ctx.GLTF.GetArrayFromAccessor<Vector3>(prim.attributes.POSITION);
var positions = gltf.GetArrayFromAccessor<Vector3>(prim.attributes.POSITION);
var fillLength = m_positions.Count;
m_positions.AddRange(positions.Select(inverter.InvertVector3));
// normal
if (prim.attributes.NORMAL != -1)
{
var normals = ctx.GLTF.GetArrayFromAccessor<Vector3>(prim.attributes.NORMAL);
var normals = gltf.GetArrayFromAccessor<Vector3>(prim.attributes.NORMAL);
if (normals.Length != positions.Length)
{
throw new Exception("different length");
@@ -151,7 +151,7 @@ namespace UniGLTF
#if false
if (prim.attributes.TANGENT != -1)
{
var tangents = ctx.GLTF.GetArrayFromAccessor<Vector4>(prim.attributes.TANGENT);
var tangents = gltf.GetArrayFromAccessor<Vector4>(prim.attributes.TANGENT);
if (tangents.Length != positions.Length)
{
throw new Exception("different length");
@@ -164,12 +164,12 @@ namespace UniGLTF
// uv
if (prim.attributes.TEXCOORD_0 != -1)
{
var uvs = ctx.GLTF.GetArrayFromAccessor<Vector2>(prim.attributes.TEXCOORD_0);
var uvs = gltf.GetArrayFromAccessor<Vector2>(prim.attributes.TEXCOORD_0);
if (uvs.Length != positions.Length)
{
throw new Exception("different length");
}
if (ctx.Parser.IsGeneratedUniGLTFAndOlder(1, 16))
if (gltf.IsGeneratedUniGLTFAndOlder(1, 16))
{
#pragma warning disable 0612
// backward compatibility
@@ -187,7 +187,7 @@ namespace UniGLTF
// uv2
if (prim.attributes.TEXCOORD_1 != -1)
{
var uvs = ctx.GLTF.GetArrayFromAccessor<Vector2>(prim.attributes.TEXCOORD_1);
var uvs = gltf.GetArrayFromAccessor<Vector2>(prim.attributes.TEXCOORD_1);
if (uvs.Length != positions.Length)
{
throw new Exception("different length");
@@ -199,7 +199,7 @@ namespace UniGLTF
// color
if (prim.attributes.COLOR_0 != -1)
{
var colors = ctx.GLTF.GetArrayFromAccessor<Color>(prim.attributes.COLOR_0);
var colors = gltf.GetArrayFromAccessor<Color>(prim.attributes.COLOR_0);
if (colors.Length != positions.Length)
{
throw new Exception("different length");
@@ -211,8 +211,8 @@ namespace UniGLTF
// skin
if (prim.attributes.JOINTS_0 != -1 && prim.attributes.WEIGHTS_0 != -1)
{
var (joints0, jointsLength) = JointsAccessor.GetAccessor(ctx.GLTF, prim.attributes.JOINTS_0);
var (weights0, weightsLength) = WeightsAccessor.GetAccessor(ctx.GLTF, prim.attributes.WEIGHTS_0);
var (joints0, jointsLength) = JointsAccessor.GetAccessor(gltf, prim.attributes.JOINTS_0);
var (weights0, weightsLength) = WeightsAccessor.GetAccessor(gltf, prim.attributes.WEIGHTS_0);
if (jointsLength != positions.Length)
{
throw new Exception("different length");
@@ -256,7 +256,7 @@ namespace UniGLTF
var blendShape = new BlendShape(i.ToString());
if (primTarget.POSITION != -1)
{
var array = ctx.GLTF.GetArrayFromAccessor<Vector3>(primTarget.POSITION);
var array = gltf.GetArrayFromAccessor<Vector3>(primTarget.POSITION);
if (array.Length != positions.Length)
{
throw new Exception("different length");
@@ -266,7 +266,7 @@ namespace UniGLTF
}
if (primTarget.NORMAL != -1)
{
var array = ctx.GLTF.GetArrayFromAccessor<Vector3>(primTarget.NORMAL);
var array = gltf.GetArrayFromAccessor<Vector3>(primTarget.NORMAL);
if (array.Length != positions.Length)
{
throw new Exception("different length");
@@ -276,7 +276,7 @@ namespace UniGLTF
}
if (primTarget.TANGENT != -1)
{
var array = ctx.GLTF.GetArrayFromAccessor<Vector3>(primTarget.TANGENT);
var array = gltf.GetArrayFromAccessor<Vector3>(primTarget.TANGENT);
if (array.Length != positions.Length)
{
throw new Exception("different length");
@@ -290,7 +290,7 @@ namespace UniGLTF
var indices =
(indexBuffer >= 0)
? ctx.GLTF.GetIndices(indexBuffer)
? gltf.GetIndices(indexBuffer)
: TriangleUtil.FlipTriangle(Enumerable.Range(0, m_positions.Count)).ToArray() // without index array
;
for (int i = 0; i < indices.Length; ++i)
@@ -313,55 +313,55 @@ namespace UniGLTF
/// <param name="ctx"></param>
/// <param name="gltfMesh"></param>
/// <returns></returns>
public void ImportMeshSharingVertexBuffer(ImporterContext ctx, glTFMesh gltfMesh, IAxisInverter inverter)
public void ImportMeshSharingVertexBuffer(glTF gltf, glTFMesh gltfMesh, IAxisInverter inverter)
{
{
// 同じVertexBufferを共有しているので先頭のモを使う
var prim = gltfMesh.primitives.First();
m_positions.AddRange(ctx.GLTF.GetArrayFromAccessor<Vector3>(prim.attributes.POSITION).SelectInplace(inverter.InvertVector3));
m_positions.AddRange(gltf.GetArrayFromAccessor<Vector3>(prim.attributes.POSITION).SelectInplace(inverter.InvertVector3));
// normal
if (prim.attributes.NORMAL != -1)
{
m_normals.AddRange(ctx.GLTF.GetArrayFromAccessor<Vector3>(prim.attributes.NORMAL).SelectInplace(inverter.InvertVector3));
m_normals.AddRange(gltf.GetArrayFromAccessor<Vector3>(prim.attributes.NORMAL).SelectInplace(inverter.InvertVector3));
}
#if false
// tangent
if (prim.attributes.TANGENT != -1)
{
tangents.AddRange(ctx.GLTF.GetArrayFromAccessor<Vector4>(prim.attributes.TANGENT).SelectInplace(inverter.InvertVector4));
tangents.AddRange(gltf.GetArrayFromAccessor<Vector4>(prim.attributes.TANGENT).SelectInplace(inverter.InvertVector4));
}
#endif
// uv
if (prim.attributes.TEXCOORD_0 != -1)
{
if (ctx.Parser.IsGeneratedUniGLTFAndOlder(1, 16))
if (gltf.IsGeneratedUniGLTFAndOlder(1, 16))
{
#pragma warning disable 0612
// backward compatibility
m_uv.AddRange(ctx.GLTF.GetArrayFromAccessor<Vector2>(prim.attributes.TEXCOORD_0).SelectInplace(x => x.ReverseY()));
m_uv.AddRange(gltf.GetArrayFromAccessor<Vector2>(prim.attributes.TEXCOORD_0).SelectInplace(x => x.ReverseY()));
#pragma warning restore 0612
}
else
{
m_uv.AddRange(ctx.GLTF.GetArrayFromAccessor<Vector2>(prim.attributes.TEXCOORD_0).SelectInplace(x => x.ReverseUV()));
m_uv.AddRange(gltf.GetArrayFromAccessor<Vector2>(prim.attributes.TEXCOORD_0).SelectInplace(x => x.ReverseUV()));
}
}
// uv2
if (prim.attributes.TEXCOORD_1 != -1)
{
m_uv2.AddRange(ctx.GLTF.GetArrayFromAccessor<Vector2>(prim.attributes.TEXCOORD_1).SelectInplace(x => x.ReverseUV()));
m_uv2.AddRange(gltf.GetArrayFromAccessor<Vector2>(prim.attributes.TEXCOORD_1).SelectInplace(x => x.ReverseUV()));
}
// color
if (prim.attributes.COLOR_0 != -1)
{
if (ctx.GLTF.accessors[prim.attributes.COLOR_0].TypeCount == 3)
if (gltf.accessors[prim.attributes.COLOR_0].TypeCount == 3)
{
var vec3Color = ctx.GLTF.GetArrayFromAccessor<Vector3>(prim.attributes.COLOR_0);
var vec3Color = gltf.GetArrayFromAccessor<Vector3>(prim.attributes.COLOR_0);
m_colors.AddRange(new Color[vec3Color.Length]);
for (int i = 0; i < vec3Color.Length; i++)
@@ -370,21 +370,21 @@ namespace UniGLTF
m_colors[i] = new Color(color.x, color.y, color.z);
}
}
else if (ctx.GLTF.accessors[prim.attributes.COLOR_0].TypeCount == 4)
else if (gltf.accessors[prim.attributes.COLOR_0].TypeCount == 4)
{
m_colors.AddRange(ctx.GLTF.GetArrayFromAccessor<Color>(prim.attributes.COLOR_0));
m_colors.AddRange(gltf.GetArrayFromAccessor<Color>(prim.attributes.COLOR_0));
}
else
{
throw new NotImplementedException(string.Format("unknown color type {0}", ctx.GLTF.accessors[prim.attributes.COLOR_0].type));
throw new NotImplementedException(string.Format("unknown color type {0}", gltf.accessors[prim.attributes.COLOR_0].type));
}
}
// skin
if (prim.attributes.JOINTS_0 != -1 && prim.attributes.WEIGHTS_0 != -1)
{
var (joints0, jointsLength) = JointsAccessor.GetAccessor(ctx.GLTF, prim.attributes.JOINTS_0);
var (weights0, weightsLength) = WeightsAccessor.GetAccessor(ctx.GLTF, prim.attributes.WEIGHTS_0);
var (joints0, jointsLength) = JointsAccessor.GetAccessor(gltf, prim.attributes.JOINTS_0);
var (weights0, weightsLength) = WeightsAccessor.GetAccessor(gltf, prim.attributes.WEIGHTS_0);
for (int j = 0; j < jointsLength; ++j)
{
@@ -424,17 +424,17 @@ namespace UniGLTF
if (primTarget.POSITION != -1)
{
blendShape.Positions.Assign(
ctx.GLTF.GetArrayFromAccessor<Vector3>(primTarget.POSITION), inverter.InvertVector3);
gltf.GetArrayFromAccessor<Vector3>(primTarget.POSITION), inverter.InvertVector3);
}
if (primTarget.NORMAL != -1)
{
blendShape.Normals.Assign(
ctx.GLTF.GetArrayFromAccessor<Vector3>(primTarget.NORMAL), inverter.InvertVector3);
gltf.GetArrayFromAccessor<Vector3>(primTarget.NORMAL), inverter.InvertVector3);
}
if (primTarget.TANGENT != -1)
{
blendShape.Tangents.Assign(
ctx.GLTF.GetArrayFromAccessor<Vector3>(primTarget.TANGENT), inverter.InvertVector3);
gltf.GetArrayFromAccessor<Vector3>(primTarget.TANGENT), inverter.InvertVector3);
}
}
}
@@ -448,7 +448,7 @@ namespace UniGLTF
}
else
{
var indices = ctx.GLTF.GetIndices(prim.indices);
var indices = gltf.GetIndices(prim.indices);
m_subMeshes.Add(indices);
}
@@ -530,18 +530,18 @@ namespace UniGLTF
return sharedAttributes;
}
public MeshContext ReadMesh(ImporterContext ctx, int meshIndex, IAxisInverter inverter)
public MeshContext ReadMesh(glTF gltf, int meshIndex, IAxisInverter inverter)
{
var gltfMesh = ctx.GLTF.meshes[meshIndex];
var gltfMesh = gltf.meshes[meshIndex];
var meshContext = new MeshContext(gltfMesh.name, meshIndex);
if (HasSharedVertexBuffer(gltfMesh))
{
meshContext.ImportMeshSharingVertexBuffer(ctx, gltfMesh, inverter);
meshContext.ImportMeshSharingVertexBuffer(gltf, gltfMesh, inverter);
}
else
{
meshContext.ImportMeshIndependentVertexBuffer(ctx, gltfMesh, inverter);
meshContext.ImportMeshIndependentVertexBuffer(gltf, gltfMesh, inverter);
}
meshContext.RenameBlendShape(gltfMesh);

View File

@@ -64,9 +64,9 @@ namespace UniGLTF
public int? SkinIndex;
}
public static TransformWithSkin BuildHierarchy(ImporterContext context, int i)
public static TransformWithSkin BuildHierarchy(glTF gltf, int i, List<Transform> nodes, List<MeshWithMaterials> meshes)
{
var go = context.Nodes[i].gameObject;
var go = nodes[i].gameObject;
if (string.IsNullOrEmpty(go.name))
{
go.name = string.Format("node{0:000}", i);
@@ -80,12 +80,12 @@ namespace UniGLTF
//
// build hierarchy
//
var node = context.GLTF.nodes[i];
var node = gltf.nodes[i];
if (node.children != null)
{
foreach (var child in node.children)
{
context.Nodes[child].transform.SetParent(context.Nodes[i].transform,
nodes[child].transform.SetParent(nodes[i].transform,
false // node has local transform
);
}
@@ -96,7 +96,7 @@ namespace UniGLTF
//
if (node.mesh != -1)
{
var mesh = context.Meshes[node.mesh];
var mesh = meshes[node.mesh];
if (mesh.Mesh.blendShapeCount == 0 && node.skin == -1)
{
// without blendshape and bone skinning

View File

@@ -6,28 +6,28 @@ namespace UniGLTF
{
public sealed class RootAnimationImporter : IAnimationImporter
{
public void Import(ImporterContext context)
public List<AnimationClip> Import(glTF gltf, GameObject root, Axises invertAxis)
{
// animation
if (context.GLTF.animations != null && context.GLTF.animations.Any())
var animationClips = new List<AnimationClip>();
if (gltf.animations != null && gltf.animations.Any())
{
var animation = context.Root.AddComponent<Animation>();
context.AnimationClips = ImportAnimationClips(context.GLTF, context.InvertAxis);
var animation = root.AddComponent<Animation>();
animationClips.AddRange(ImportAnimationClips(gltf, invertAxis));
foreach (var clip in context.AnimationClips)
foreach (var clip in animationClips)
{
animation.AddClip(clip, clip.name);
}
if (context.AnimationClips.Count > 0)
if (animationClips.Count > 0)
{
animation.clip = context.AnimationClips.First();
animation.clip = animationClips.First();
}
}
return animationClips;
}
private List<AnimationClip> ImportAnimationClips(glTF gltf, Axises invertAxis)
private IEnumerable<AnimationClip> ImportAnimationClips(glTF gltf, Axises invertAxis)
{
var animationClips = new List<AnimationClip>();
for (var i = 0; i < gltf.animations.Count; ++i)
{
var clip = new AnimationClip();
@@ -46,10 +46,8 @@ namespace UniGLTF
animation.name = $"animation:{i}";
}
animationClips.Add(AnimationImporterUtil.ConvertAnimationClip(gltf, animation, invertAxis.Create()));
yield return AnimationImporterUtil.ConvertAnimationClip(gltf, animation, invertAxis.Create());
}
return animationClips;
}
}
}

View File

@@ -13,7 +13,7 @@ namespace UniGLTF
/// </summary>
public static class GltfTextureImporter
{
static Byte[] ToArray(ArraySegment<byte> bytes)
public static Byte[] ToArray(ArraySegment<byte> bytes)
{
if (bytes.Array == null)
{

View File

@@ -0,0 +1,75 @@
using System;
using System.IO;
namespace UniGLTF
{
/// <summary>
/// for buffer with uri read
/// </summary>
public class UriByteBuffer : IBytesBuffer
{
public string Uri
{
get;
private set;
}
Byte[] m_bytes;
public ArraySegment<byte> Bytes => new ArraySegment<byte>(m_bytes);
public UriByteBuffer(string baseDir, string uri)
{
Uri = uri;
m_bytes = ReadFromUri(baseDir, uri);
}
const string DataPrefix = "data:application/octet-stream;base64,";
const string DataPrefix2 = "data:application/gltf-buffer;base64,";
const string DataPrefix3 = "data:image/jpeg;base64,";
[Obsolete("Use ReadEmbedded(uri)")]
public static Byte[] ReadEmbeded(string uri)
{
return ReadEmbedded(uri);
}
public static Byte[] ReadEmbedded(string uri)
{
var pos = uri.IndexOf(";base64,");
if (pos < 0)
{
throw new NotImplementedException();
}
else
{
return Convert.FromBase64String(uri.Substring(pos + 8));
}
}
Byte[] ReadFromUri(string baseDir, string uri)
{
var bytes = ReadEmbedded(uri);
if (bytes != null)
{
return bytes;
}
else
{
// as local file path
return File.ReadAllBytes(Path.Combine(baseDir, uri));
}
}
public glTFBufferView Extend<T>(ArraySegment<T> array, glBufferTarget target) where T : struct
{
throw new NotImplementedException();
}
public void ExtendCapacity(int capacity)
{
throw new NotImplementedException();
}
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 1e9c9201942704b4f9dd050115073032
guid: 8b75aca0e4a7415418cd1c3d018483b2
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -66,6 +66,27 @@ namespace UniJSON
return self.ContainsKey(ukey);
}
public static bool TryGet(this JsonNode self, Utf8String key, out JsonNode found)
{
foreach (var kv in self.ObjectItems())
{
if (kv.Key.GetUtf8String() == key)
{
found = kv.Value;
return true;
}
}
found = default;
return false;
}
public static bool TryGet(this JsonNode self, String key, out JsonNode found)
{
var ukey = Utf8String.From(key);
return self.TryGet(ukey, out found);
}
public static Utf8String KeyOf(this JsonNode self, JsonNode node)
{
foreach (var kv in self.ObjectItems())

View File

@@ -99,7 +99,7 @@ namespace UniGLTF
}
// should unique
var gltfTextures = GltfTextureEnumerator.Enumerate(parser).ToArray();
var gltfTextures = GltfTextureEnumerator.EnumerateAllTexturesDistinct(parser).ToArray();
var distinct = gltfTextures.Distinct().ToArray();
Assert.True(gltfTextures.SequenceEqual(distinct));
}

View File

@@ -207,7 +207,7 @@ namespace UniGLTF
{
GLTF = TwoTexture(),
};
var items = GltfTextureEnumerator.Enumerate(parser).ToArray();
var items = GltfTextureEnumerator.EnumerateAllTexturesDistinct(parser).ToArray();
Assert.AreEqual(2, items.Length);
}
@@ -216,7 +216,7 @@ namespace UniGLTF
{
GLTF = TwoTextureOneUri(),
};
var items = GltfTextureEnumerator.Enumerate(parser).ToArray();
var items = GltfTextureEnumerator.EnumerateAllTexturesDistinct(parser).ToArray();
Assert.AreEqual(1, items.Length);
}
@@ -225,7 +225,7 @@ namespace UniGLTF
{
GLTF = TwoTextureOneImage(),
};
var items = GltfTextureEnumerator.Enumerate(parser).ToArray();
var items = GltfTextureEnumerator.EnumerateAllTexturesDistinct(parser).ToArray();
Assert.AreEqual(1, items.Length);
}
@@ -234,7 +234,7 @@ namespace UniGLTF
{
GLTF = CombineMetallicSmoothOcclusion(),
};
var items = GltfTextureEnumerator.Enumerate(parser).ToArray();
var items = GltfTextureEnumerator.EnumerateAllTexturesDistinct(parser).ToArray();
Assert.AreEqual(1, items.Length);
}
}

View File

@@ -185,12 +185,12 @@ namespace UniGLTF
[Test]
public void VersionChecker()
{
Assert.False(GltfParser.IsGeneratedUniGLTFAndOlderThan("hoge", 1, 16));
Assert.False(GltfParser.IsGeneratedUniGLTFAndOlderThan("UniGLTF-1.16", 1, 16));
Assert.True(GltfParser.IsGeneratedUniGLTFAndOlderThan("UniGLTF-1.15", 1, 16));
Assert.False(GltfParser.IsGeneratedUniGLTFAndOlderThan("UniGLTF-11.16", 1, 16));
Assert.True(GltfParser.IsGeneratedUniGLTFAndOlderThan("UniGLTF-0.16", 1, 16));
Assert.True(GltfParser.IsGeneratedUniGLTFAndOlderThan("UniGLTF", 1, 16));
Assert.False(glTFExtensions.IsGeneratedUniGLTFAndOlderThan("hoge", 1, 16));
Assert.False(glTFExtensions.IsGeneratedUniGLTFAndOlderThan("UniGLTF-1.16", 1, 16));
Assert.True(glTFExtensions.IsGeneratedUniGLTFAndOlderThan("UniGLTF-1.15", 1, 16));
Assert.False(glTFExtensions.IsGeneratedUniGLTFAndOlderThan("UniGLTF-11.16", 1, 16));
Assert.True(glTFExtensions.IsGeneratedUniGLTFAndOlderThan("UniGLTF-0.16", 1, 16));
Assert.True(glTFExtensions.IsGeneratedUniGLTFAndOlderThan("UniGLTF", 1, 16));
}
[Test]

View File

@@ -149,9 +149,9 @@ namespace VRM
.Where(x => x.IsUsed)
.Select(x => x.Texture)
.ToArray();
var vrmTextures = new VRMTextureEnumerator(m_context.VRM);
var vrmTextures = new VRMMtoonMaterialImporter(m_context.VRM);
var dirName = $"{m_prefabPath.FileNameWithoutExtension}.Textures";
TextureExtractor.ExtractTextures(m_context.Parser, m_prefabPath.Parent.Child(dirName), vrmTextures.Enumerate, subAssets, _ => { }, onTextureReloaded);
TextureExtractor.ExtractTextures(m_context.Parser, m_prefabPath.Parent.Child(dirName), vrmTextures.EnumerateAllTexturesDistinct, subAssets, _ => { }, onTextureReloaded);
}
bool SaveAsAsset(UnityEngine.Object o)

View File

@@ -83,7 +83,7 @@ namespace VRM
using (var context = new VRMImporterContext(parser, map))
{
var editor = new VRMEditorImporterContext(context, prefabPath);
foreach (var textureInfo in new VRMTextureEnumerator(context.VRM).Enumerate(parser))
foreach (var textureInfo in new VRMMtoonMaterialImporter(context.VRM).EnumerateAllTexturesDistinct(parser))
{
TextureImporterConfigurator.Configure(textureInfo, map.ToDictionary(x => x.name, x => x.texture as Texture2D));
}

View File

@@ -60,7 +60,7 @@ namespace VRM
using (var context = new VRMImporterContext(parser, map))
{
var editor = new VRMEditorImporterContext(context, prefabPath);
foreach (var textureInfo in new VRMTextureEnumerator(context.VRM).Enumerate(parser))
foreach (var textureInfo in new VRMMtoonMaterialImporter(context.VRM).EnumerateAllTexturesDistinct(parser))
{
TextureImporterConfigurator.Configure(textureInfo, map.ToDictionary(x => x.name, x => x.texture as Texture2D));
}

View File

@@ -26,7 +26,7 @@ namespace VRM
{
VRM = vrm;
// override material importer
GltfMaterialImporter.GltfMaterialParamProcessors.Insert(0, new MToonMaterialImporter(VRM.materialProperties).TryCreateParam);
GltfMaterialImporter.GltfMaterialParamProcessors.Insert(0, new VRMMtoonMaterialImporter(VRM).TryCreateParam);
}
else
{
@@ -35,7 +35,7 @@ namespace VRM
}
#region OnLoad
protected override async Task OnLoadModel(IAwaitCaller awaitCaller, Func<string, IDisposable> MeasureTime)
protected override async Task OnLoadHierarchy(IAwaitCaller awaitCaller, Func<string, IDisposable> MeasureTime)
{
Root.name = "VRM";

View File

@@ -3,13 +3,19 @@ using UniGLTF;
using UnityEngine;
using VRMShaders;
namespace VRM
{
public class MToonMaterialImporter
public class VRMMtoonMaterialImporter
{
public static bool TryCreateParam(GltfParser parser, int i, glTF_VRM_Material vrmMaterial, out MaterialImportParam param)
readonly glTF_VRM_extensions m_vrm;
public VRMMtoonMaterialImporter(glTF_VRM_extensions vrm)
{
m_vrm = vrm;
}
public bool TryCreateParam(GltfParser parser, int i, out MaterialImportParam param)
{
var vrmMaterial = m_vrm.materialProperties[i];
if (vrmMaterial.shader == VRM.glTF_VRM_Material.VRM_USE_GLTFSHADER)
{
// fallback to gltf
@@ -87,21 +93,64 @@ namespace VRM
return true;
}
List<glTF_VRM_Material> m_materials;
public MToonMaterialImporter(List<glTF_VRM_Material> materials)
public IEnumerable<TextureImportParam> EnumerateTexturesForMaterial(GltfParser parser, int i)
{
m_materials = materials;
}
public bool TryCreateParam(GltfParser parser, int i, out MaterialImportParam param)
{
if (TryCreateParam(parser, i, m_materials[i], out param))
// mtoon
if (!TryCreateParam(parser, i, out MaterialImportParam param))
{
return true;
// unlit
if (!GltfUnlitMaterial.TryCreateParam(parser, i, out param))
{
// pbr
GltfPBRMaterial.TryCreateParam(parser, i, out param);
}
}
param = default;
return false;
foreach (var kv in param.TextureSlots)
{
yield return kv.Value;
}
}
public IEnumerable<TextureImportParam> EnumerateAllTexturesDistinct(GltfParser parser)
{
var used = new HashSet<string>();
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))
{
if (used.Add(textureInfo.ExtractKey))
{
yield return textureInfo;
}
}
}
else
{
// PBR or Unlit
foreach (var textureInfo in GltfTextureEnumerator.EnumerateTexturesForMaterial(parser, i))
{
if (used.Add(textureInfo.ExtractKey))
{
yield return textureInfo;
}
}
}
}
// 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))
{
yield return textureInfo;
}
}
}
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 8e6d15fc36df79649bb4724b06b5eae3
guid: bad75b40d017eb74ba79f561d22dc372
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -1,83 +0,0 @@
using System.Collections.Generic;
using UniGLTF;
using UnityEngine;
using VRMShaders;
namespace VRM
{
public class VRMTextureEnumerator
{
readonly glTF_VRM_extensions m_vrm;
public VRMTextureEnumerator(glTF_VRM_extensions vrm)
{
m_vrm = vrm;
}
public IEnumerable<TextureImportParam> EnumerateMaterial(GltfParser parser, glTF_VRM_Material vrmMaterial)
{
// MToon
var offsetScaleMap = new Dictionary<string, float[]>();
foreach (var kv in vrmMaterial.vectorProperties)
{
if (vrmMaterial.textureProperties.ContainsKey(kv.Key))
{
// texture offset & scale
offsetScaleMap.Add(kv.Key, kv.Value);
}
}
foreach (var kv in vrmMaterial.textureProperties)
{
var (offset, scale) = (Vector2.zero, Vector2.one);
if (offsetScaleMap.TryGetValue(kv.Key, out float[] value))
{
offset = new Vector2(value[0], value[1]);
scale = new Vector2(value[2], value[3]);
}
// SRGB color or normalmap
yield return MToonTextureParam.Create(parser, kv.Value, offset, scale, kv.Key, default, default);
}
}
public IEnumerable<TextureImportParam> Enumerate(GltfParser parser)
{
var used = new HashSet<string>();
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 EnumerateMaterial(parser, vrmMaterial))
{
if (used.Add(textureInfo.ExtractKey))
{
yield return textureInfo;
}
}
}
else
{
// PBR or Unlit
foreach (var textureInfo in GltfTextureEnumerator.EnumerateTextures(parser, parser.GLTF.materials[i]))
{
if (used.Add(textureInfo.ExtractKey))
{
yield return textureInfo;
}
}
}
}
// 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))
{
yield return textureInfo;
}
}
}
}
}

View File

@@ -24,12 +24,15 @@ namespace VRM
srcMaterial.mainTexture = tex0;
srcMaterial.mainTextureOffset = offset;
srcMaterial.mainTextureScale = scale;
var materialExporter = new VRMMaterialExporter();
var vrmMaterial = VRMMaterialExporter.CreateFromMaterial(srcMaterial, textureManager);
Assert.AreEqual(vrmMaterial.vectorProperties["_MainTex"], new float[]{0.3f, 0.2f, 0.5f, 0.6f});
var materialImporter = new MToonMaterialImporter(new System.Collections.Generic.List<glTF_VRM_Material>{ vrmMaterial });
Assert.AreEqual(vrmMaterial.vectorProperties["_MainTex"], new float[] { 0.3f, 0.2f, 0.5f, 0.6f });
var materialImporter = new VRMMtoonMaterialImporter(new glTF_VRM_extensions
{
materialProperties = new System.Collections.Generic.List<glTF_VRM_Material> { vrmMaterial }
});
}
}
}

View File

@@ -71,7 +71,7 @@ namespace VRM
},
}
};
var items = new VRMTextureEnumerator(vrm).Enumerate(parser).ToArray();
var items = new VRMMtoonMaterialImporter(vrm).EnumerateAllTexturesDistinct(parser).ToArray();
Assert.AreEqual(1, items.Length);
}
}

View File

@@ -26,7 +26,7 @@ namespace UniVRM10.Samples
}
}
IEnumerator RoutineNest(VrmLib.ExpressionPreset preset, float velocity, float wait)
IEnumerator RoutineNest(UniGLTF.Extensions.VRMC_vrm.ExpressionPreset preset, float velocity, float wait)
{
for (var value = 0.0f; value <= 1.0f; value += velocity)
{
@@ -52,11 +52,11 @@ namespace UniVRM10.Samples
var velocity = 0.1f;
yield return RoutineNest(VrmLib.ExpressionPreset.Aa, velocity, m_wait);
yield return RoutineNest(VrmLib.ExpressionPreset.Ih, velocity, m_wait);
yield return RoutineNest(VrmLib.ExpressionPreset.Ou, velocity, m_wait);
yield return RoutineNest(VrmLib.ExpressionPreset.Ee, velocity, m_wait);
yield return RoutineNest(VrmLib.ExpressionPreset.Oh, velocity, m_wait);
yield return RoutineNest(UniGLTF.Extensions.VRMC_vrm.ExpressionPreset.aa, velocity, m_wait);
yield return RoutineNest(UniGLTF.Extensions.VRMC_vrm.ExpressionPreset.ih, velocity, m_wait);
yield return RoutineNest(UniGLTF.Extensions.VRMC_vrm.ExpressionPreset.ou, velocity, m_wait);
yield return RoutineNest(UniGLTF.Extensions.VRMC_vrm.ExpressionPreset.ee, velocity, m_wait);
yield return RoutineNest(UniGLTF.Extensions.VRMC_vrm.ExpressionPreset.oh, velocity, m_wait);
}
}

View File

@@ -72,10 +72,10 @@ namespace UniVRM10.Samples
break;
}
m_controller.Expression.SetWeight(ExpressionKey.CreateFromPreset(VrmLib.ExpressionPreset.Blink), value);
m_controller.Expression.SetWeight(ExpressionKey.CreateFromPreset(UniGLTF.Extensions.VRMC_vrm.ExpressionPreset.blink), value);
yield return null;
}
m_controller.Expression.SetWeight(ExpressionKey.CreateFromPreset(VrmLib.ExpressionPreset.Blink), 1.0f);
m_controller.Expression.SetWeight(ExpressionKey.CreateFromPreset(UniGLTF.Extensions.VRMC_vrm.ExpressionPreset.blink), 1.0f);
// wait...
yield return new WaitForSeconds(ClosingTime);
@@ -91,10 +91,10 @@ namespace UniVRM10.Samples
break;
}
m_controller.Expression.SetWeight(ExpressionKey.CreateFromPreset(VrmLib.ExpressionPreset.Blink), value);
m_controller.Expression.SetWeight(ExpressionKey.CreateFromPreset(UniGLTF.Extensions.VRMC_vrm.ExpressionPreset.blink), value);
yield return null;
}
m_controller.Expression.SetWeight(ExpressionKey.CreateFromPreset(VrmLib.ExpressionPreset.Blink), 0);
m_controller.Expression.SetWeight(ExpressionKey.CreateFromPreset(UniGLTF.Extensions.VRMC_vrm.ExpressionPreset.blink), 0);
}
}

View File

@@ -84,16 +84,18 @@ namespace UniVRM10.Samples
m_textDistributionOther.text = "";
}
public void UpdateMeta(VRM10Controller context)
public void UpdateMeta(VRM10MetaObject meta)
{
// var meta = context.ReadMeta(true);
var meta = context.Meta;
if (meta == null)
{
return;
}
m_textModelTitle.text = meta.Name;
m_textModelVersion.text = meta.Version;
m_textModelAuthor.text = meta.Authors[0];
m_textModelContact.text = meta.ContactInformation;
m_textModelReference.text = meta.Reference;
m_textModelReference.text = meta.References[0];
m_textPermissionAllowed.text = meta.AllowedUser.ToString();
m_textPermissionViolent.text = meta.ViolentUsage.ToString();
@@ -306,28 +308,17 @@ namespace UniVRM10.Samples
{
case ".vrm":
{
// var context = new ImporterContext();
var file = File.ReadAllBytes(path);
// context.ParseGlb(file);
// context.Load();
// context.ShowMeshes();
// context.EnableUpdateWhenOffscreen();
// context.ShowMeshes();
var parser = new UniGLTF.GltfParser();
parser.ParsePath(path);
var model = UniVRM10.VrmLoader.CreateVrmModel(file, new FileInfo(path));
// UniVRM-0.XXのコンポーネントを構築する
var assets = UniVRM10.RuntimeUnityBuilder.ToUnityAsset(model, showMesh: false);
// showRenderer = false のときに後で表示する例
foreach (var renderer in assets.Renderers)
using (var loader = new RuntimeUnityBuilder(parser))
{
renderer.enabled = true;
loader.Load();
loader.ShowMeshes();
loader.EnableUpdateWhenOffscreen();
var destroyer = loader.DisposeOnGameObjectDestroyed();
SetModel(destroyer.gameObject);
}
UniVRM10.ComponentBuilder.Build10(model, assets);
SetModel(assets.Root);
break;
}
@@ -337,12 +328,15 @@ namespace UniVRM10.Samples
var parser = new GltfParser();
parser.ParseGlb(file);
var context = new UniGLTF.ImporterContext(parser);
context.Load();
context.ShowMeshes();
context.EnableUpdateWhenOffscreen();
context.ShowMeshes();
SetModel(context.Root);
using (var loader = new UniGLTF.ImporterContext(parser))
{
loader.Load();
loader.ShowMeshes();
loader.EnableUpdateWhenOffscreen();
loader.ShowMeshes();
var destroyer = loader.DisposeOnGameObjectDestroyed();
SetModel(destroyer.gameObject);
}
break;
}
@@ -352,12 +346,15 @@ namespace UniVRM10.Samples
var parser = new GltfParser();
parser.ParsePath(path);
var context = new UniGLTF.ImporterContext(parser);
context.Load();
context.ShowMeshes();
context.EnableUpdateWhenOffscreen();
context.ShowMeshes();
SetModel(context.Root);
using (var loader = new UniGLTF.ImporterContext(parser))
{
loader.Load();
loader.ShowMeshes();
loader.EnableUpdateWhenOffscreen();
loader.ShowMeshes();
var destroyer = loader.DisposeOnGameObjectDestroyed();
SetModel(destroyer.gameObject);
}
break;
}
@@ -382,19 +379,22 @@ namespace UniVRM10.Samples
if (go != null)
{
m_controller = go.GetComponent<VRM10Controller>();
m_texts.UpdateMeta(m_controller);
m_controller.Controller.UpdateType = VRM10Controller.VRM10ControllerImpl.UpdateTypes.LateUpdate; // after HumanPoseTransfer's setPose
if (m_controller != null)
{
m_loaded = go.AddComponent<HumanPoseTransfer>();
m_loaded.Source = m_src;
m_loaded.SourceType = HumanPoseTransfer.HumanPoseTransferSourceType.HumanPoseTransfer;
m_lipSync = go.AddComponent<AIUEO>();
m_blink = go.AddComponent<Blinker>();
m_texts.UpdateMeta(m_controller.Meta);
m_controller.LookAt.Gaze = m_target.transform;
m_controller.Controller.UpdateType = VRM10Controller.VRM10ControllerImpl.UpdateTypes.LateUpdate; // after HumanPoseTransfer's setPose
{
m_loaded = go.AddComponent<HumanPoseTransfer>();
m_loaded.Source = m_src;
m_loaded.SourceType = HumanPoseTransfer.HumanPoseTransferSourceType.HumanPoseTransfer;
m_lipSync = go.AddComponent<AIUEO>();
m_blink = go.AddComponent<Blinker>();
m_controller.LookAt.Gaze = m_target.transform;
}
}
var animation = go.GetComponent<Animation>();
@@ -402,7 +402,6 @@ namespace UniVRM10.Samples
{
animation.Play(animation.clip.name);
}
}
}

View File

@@ -275,24 +275,5 @@ namespace UniVRM10
}
}
}
public override string GetInfoString()
{
var expression = CurrentExpression();
if (expression == null)
{
return "no expression";
}
var key = ExpressionKey.CreateFromClip(expression);
if (key.Preset != VrmLib.ExpressionPreset.Custom)
{
return string.Format("Preset: {0}", key.Preset);
}
else
{
return string.Format("Custom: {0}", key.Name);
}
}
}
}

View File

@@ -52,7 +52,7 @@ namespace UniVRM10
// 対象のプロパティを enum から選択する
var bindTypeProp = property.FindPropertyRelative("BindType");
var bindTypes = (VrmLib.MaterialBindType[])Enum.GetValues(typeof(VrmLib.MaterialBindType));
var bindTypes = (UniGLTF.Extensions.VRMC_vrm.MaterialColorType[])Enum.GetValues(typeof(UniGLTF.Extensions.VRMC_vrm.MaterialColorType));
var bindType = bindTypes[bindTypeProp.enumValueIndex];
var newBindType = ExpressionEditorHelper.EnumPopup(rect, bindType);
if (newBindType != bindType)

View File

@@ -58,7 +58,6 @@ namespace UniVRM10
m_lookAt = PropGui.FromObject(serializedObject, nameof(m_target.LookAt));
m_firstPerson = PropGui.FromObject(serializedObject, nameof(m_target.FirstPerson));
m_springBone = PropGui.FromObject(serializedObject, nameof(m_target.SpringBone));
m_asset = PropGui.FromObject(serializedObject, nameof(m_target.ModelAsset));
}
void OnDisable()
@@ -78,7 +77,6 @@ namespace UniVRM10
LookAt,
FirstPerson,
SpringBone,
Assets,
}
Tabs _tab;
@@ -136,7 +134,7 @@ namespace UniVRM10
}
serializedObject.Update();
// Setup runtime function.
m_target.Setup();
@@ -167,10 +165,6 @@ namespace UniVRM10
case Tabs.SpringBone:
m_springBone.RecursiveProperty();
break;
case Tabs.Assets:
m_asset.RecursiveProperty();
break;
}
serializedObject.ApplyModifiedProperties();
@@ -194,7 +188,7 @@ namespace UniVRM10
{
EditorGUILayout.Space();
EditorGUILayout.LabelField("Expression Weights", EditorStyles.boldLabel);
var sliders = m_sliders.Select(x => x.Slider());
foreach (var slider in sliders)
{
@@ -202,7 +196,7 @@ namespace UniVRM10
}
m_target.Expression.SetWeights(m_expressionKeyWeights);
}
EditorGUILayout.Space();
EditorGUILayout.LabelField("Override rates", EditorStyles.boldLabel);
EditorGUI.BeginDisabledGroup(true);

View File

@@ -8,132 +8,132 @@ namespace UniVRM10
{
public static class EditorUnityBuilder
{
static public ModelAsset ToUnityAsset(VrmLib.Model model, string assetPath, IExternalUnityObject scriptedImporter)
{
var modelAsset = new ModelAsset();
CreateTextureAsset(model, modelAsset, scriptedImporter);
CreateMaterialAsset(model, modelAsset, scriptedImporter);
CreateMeshAsset(model, modelAsset);
// static public ModelAsset ToUnityAsset(VrmLib.Model model, string assetPath, IExternalUnityObject scriptedImporter)
// {
// var modelAsset = new ModelAsset();
// CreateTextureAsset(model, modelAsset, scriptedImporter);
// CreateMaterialAsset(model, modelAsset, scriptedImporter);
// CreateMeshAsset(model, modelAsset);
// node
RuntimeUnityBuilder.CreateNodes(model.Root, null, modelAsset.Map.Nodes);
modelAsset.Root = modelAsset.Map.Nodes[model.Root];
// // node
// RuntimeUnityBuilder.CreateNodes(model.Root, null, modelAsset.Map.Nodes);
// modelAsset.Root = modelAsset.Map.Nodes[model.Root];
// renderer
var map = modelAsset.Map;
foreach (var (node, go) in map.Nodes)
{
if (node.MeshGroup is null)
{
continue;
}
// // renderer
// var map = modelAsset.Map;
// foreach (var (node, go) in map.Nodes)
// {
// if (node.MeshGroup is null)
// {
// continue;
// }
if (node.MeshGroup.Meshes.Count > 1)
{
throw new NotImplementedException("invalid isolated vertexbuffer");
}
// if (node.MeshGroup.Meshes.Count > 1)
// {
// throw new NotImplementedException("invalid isolated vertexbuffer");
// }
var renderer = RuntimeUnityBuilder.CreateRenderer(node, go, map);
map.Renderers.Add(node, renderer);
modelAsset.Renderers.Add(renderer);
}
// var renderer = RuntimeUnityBuilder.CreateRenderer(node, go, map);
// map.Renderers.Add(node, renderer);
// modelAsset.Renderers.Add(renderer);
// }
if (model.Vrm != null)
{
// humanoid
var humanoid = modelAsset.Root.AddComponent<MeshUtility.Humanoid>();
humanoid.AssignBones(modelAsset.Map.Nodes.Select(x => (x.Key.HumanoidBone.GetValueOrDefault().ToUnity(), x.Value.transform)));
modelAsset.HumanoidAvatar = humanoid.CreateAvatar();
modelAsset.HumanoidAvatar.name = "VRM";
// if (model.Vrm != null)
// {
// // humanoid
// var humanoid = modelAsset.Root.AddComponent<MeshUtility.Humanoid>();
// humanoid.AssignBones(modelAsset.Map.Nodes.Select(x => (x.Key.HumanoidBone.GetValueOrDefault().ToUnity(), x.Value.transform)));
// modelAsset.HumanoidAvatar = humanoid.CreateAvatar();
// modelAsset.HumanoidAvatar.name = "VRM";
var animator = modelAsset.Root.AddComponent<Animator>();
animator.avatar = modelAsset.HumanoidAvatar;
}
// var animator = modelAsset.Root.AddComponent<Animator>();
// animator.avatar = modelAsset.HumanoidAvatar;
// }
return modelAsset;
}
// return modelAsset;
// }
static private void CreateTextureAsset(VrmLib.Model model, ModelAsset modelAsset, IExternalUnityObject scriptedImporter)
{
var externalObjects = scriptedImporter.GetExternalUnityObjects<Texture2D>();
// static private void CreateTextureAsset(VrmLib.Model model, ModelAsset modelAsset, IExternalUnityObject scriptedImporter)
// {
// var externalObjects = scriptedImporter.GetExternalUnityObjects<Texture2D>();
// textures
for (int i = 0; i < model.Textures.Count; ++i)
{
if (model.Textures[i] is VrmLib.ImageTexture imageTexture)
{
if (string.IsNullOrEmpty(model.Textures[i].Name))
{
model.Textures[i].Name = string.Format("{0}_img{1}", model.Root.Name, i);
}
if (externalObjects.ContainsKey(model.Textures[i].Name))
{
modelAsset.Map.Textures.Add(imageTexture, externalObjects[model.Textures[i].Name]);
modelAsset.Textures.Add(externalObjects[model.Textures[i].Name]);
}
else
{
var name = !string.IsNullOrEmpty(imageTexture.Name)
? imageTexture.Name
: string.Format("{0}_img{1}", model.Root.Name, i);
// // textures
// for (int i = 0; i < model.Textures.Count; ++i)
// {
// if (model.Textures[i] is VrmLib.ImageTexture imageTexture)
// {
// if (string.IsNullOrEmpty(model.Textures[i].Name))
// {
// model.Textures[i].Name = string.Format("{0}_img{1}", model.Root.Name, i);
// }
// if (externalObjects.ContainsKey(model.Textures[i].Name))
// {
// modelAsset.Map.Textures.Add(imageTexture, externalObjects[model.Textures[i].Name]);
// modelAsset.Textures.Add(externalObjects[model.Textures[i].Name]);
// }
// else
// {
// var name = !string.IsNullOrEmpty(imageTexture.Name)
// ? imageTexture.Name
// : string.Format("{0}_img{1}", model.Root.Name, i);
var texture = RuntimeUnityBuilder.CreateTexture(imageTexture);
texture.name = name;
// var texture = RuntimeUnityBuilder.CreateTexture(imageTexture);
// texture.name = name;
modelAsset.Map.Textures.Add(imageTexture, texture);
modelAsset.Textures.Add(texture);
}
}
else
{
Debug.LogWarning($"{i} not ImageTexture");
}
}
}
// modelAsset.Map.Textures.Add(imageTexture, texture);
// modelAsset.Textures.Add(texture);
// }
// }
// else
// {
// Debug.LogWarning($"{i} not ImageTexture");
// }
// }
// }
static private void CreateMaterialAsset(VrmLib.Model model, ModelAsset modelAsset, IExternalUnityObject scriptedImporter)
{
var externalObjects = scriptedImporter.GetExternalUnityObjects<UnityEngine.Material>();
// static private void CreateMaterialAsset(VrmLib.Model model, ModelAsset modelAsset, IExternalUnityObject scriptedImporter)
// {
// var externalObjects = scriptedImporter.GetExternalUnityObjects<UnityEngine.Material>();
foreach (var src in model.Materials)
{
if (externalObjects.ContainsKey(src.Name))
{
modelAsset.Map.Materials.Add(src, externalObjects[src.Name]);
modelAsset.Materials.Add(externalObjects[src.Name]);
}
else
{
// TODO: material has VertexColor
var material = RuntimeUnityMaterialBuilder.CreateMaterialAsset(src, hasVertexColor: false, modelAsset.Map.Textures);
material.name = src.Name;
modelAsset.Map.Materials.Add(src, material);
modelAsset.Materials.Add(material);
}
}
}
// foreach (var src in model.Materials)
// {
// if (externalObjects.ContainsKey(src.Name))
// {
// modelAsset.Map.Materials.Add(src, externalObjects[src.Name]);
// modelAsset.Materials.Add(externalObjects[src.Name]);
// }
// else
// {
// // TODO: material has VertexColor
// var material = RuntimeUnityMaterialBuilder.CreateMaterialAsset(src, hasVertexColor: false, modelAsset.Map.Textures);
// material.name = src.Name;
// modelAsset.Map.Materials.Add(src, material);
// modelAsset.Materials.Add(material);
// }
// }
// }
static private void CreateMeshAsset(VrmLib.Model model, ModelAsset modelAsset)
{
for (int i = 0; i < model.MeshGroups.Count; ++i)
{
var src = model.MeshGroups[i];
if (src.Meshes.Count == 1)
{
// submesh 方式
var mesh = new UnityEngine.Mesh();
mesh.name = src.Name;
mesh.LoadMesh(src.Meshes[0], src.Skin);
modelAsset.Map.Meshes.Add(src, mesh);
modelAsset.Meshes.Add(mesh);
}
else
{
// 頂点バッファの連結が必用
throw new NotImplementedException();
}
}
}
// static private void CreateMeshAsset(VrmLib.Model model, ModelAsset modelAsset)
// {
// for (int i = 0; i < model.MeshGroups.Count; ++i)
// {
// var src = model.MeshGroups[i];
// if (src.Meshes.Count == 1)
// {
// // submesh 方式
// var mesh = new UnityEngine.Mesh();
// mesh.name = src.Name;
// mesh.LoadMesh(src.Meshes[0], src.Skin);
// modelAsset.Map.Meshes.Add(src, mesh);
// modelAsset.Meshes.Add(mesh);
// }
// else
// {
// // 頂点バッファの連結が必用
// throw new NotImplementedException();
// }
// }
// }
}
}

View File

@@ -1,12 +0,0 @@
using System.Collections.Generic;
namespace UniVRM10
{
public interface IExternalUnityObject
{
Dictionary<string, T> GetExternalUnityObjects<T>() where T : UnityEngine.Object;
void SetExternalUnityObject<T>(UnityEditor.AssetImporter.SourceAssetIdentifier sourceAssetIdentifier, T obj) where T : UnityEngine.Object;
}
}

View File

@@ -1,181 +0,0 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
using System;
using UnityEngine;
#if UNITY_2020_2_OR_NEWER
using UnityEditor.AssetImporters;
#else
using UnityEditor.Experimental.AssetImporters;
#endif
namespace UniVRM10
{
public static class ScriptedImporterExtension
{
public static void ClearExternalObjects<T>(this ScriptedImporter importer) where T : UnityEngine.Object
{
foreach (var extarnalObject in importer.GetExternalObjectMap().Where(x => x.Key.type == typeof(T)))
{
importer.RemoveRemap(extarnalObject.Key);
}
AssetDatabase.WriteImportSettingsIfDirty(importer.assetPath);
AssetDatabase.ImportAsset(importer.assetPath, ImportAssetOptions.ForceUpdate);
}
public static void ClearExtarnalObjects(this ScriptedImporter importer)
{
foreach (var extarnalObject in importer.GetExternalObjectMap())
{
importer.RemoveRemap(extarnalObject.Key);
}
AssetDatabase.WriteImportSettingsIfDirty(importer.assetPath);
AssetDatabase.ImportAsset(importer.assetPath, ImportAssetOptions.ForceUpdate);
}
private static T GetSubAsset<T>(this ScriptedImporter importer, string assetPath) where T : UnityEngine.Object
{
return importer.GetSubAssets<T>(assetPath)
.FirstOrDefault();
}
public static IEnumerable<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);
}
private static void ExtractFromAsset(UnityEngine.Object subAsset, string destinationPath, bool isForceUpdate)
{
string assetPath = AssetDatabase.GetAssetPath(subAsset);
var clone = UnityEngine.Object.Instantiate(subAsset);
AssetDatabase.CreateAsset(clone, destinationPath);
var assetImporter = AssetImporter.GetAtPath(assetPath);
assetImporter.AddRemap(new AssetImporter.SourceAssetIdentifier(subAsset), clone);
if (isForceUpdate)
{
AssetDatabase.WriteImportSettingsIfDirty(assetPath);
AssetDatabase.ImportAsset(assetPath, ImportAssetOptions.ForceUpdate);
}
}
public static void ExtractAssets<T>(this ScriptedImporter importer, string dirName, string extension) where T : UnityEngine.Object
{
if (string.IsNullOrEmpty(importer.assetPath))
return;
var subAssets = importer.GetSubAssets<T>(importer.assetPath);
var path = string.Format("{0}/{1}.{2}",
Path.GetDirectoryName(importer.assetPath),
Path.GetFileNameWithoutExtension(importer.assetPath),
dirName
);
var info = importer.SafeCreateDirectory(path);
foreach (var asset in subAssets)
{
ExtractFromAsset(asset, string.Format("{0}/{1}{2}", path, asset.name, extension), false);
}
}
public static void ExtractTextures(this ScriptedImporter importer, string dirName, Func<string, VrmLib.Model> CreateModel, Action onComplited = null)
{
if (string.IsNullOrEmpty(importer.assetPath))
return;
var subAssets = importer.GetSubAssets<UnityEngine.Texture2D>(importer.assetPath);
var path = string.Format("{0}/{1}.{2}",
Path.GetDirectoryName(importer.assetPath),
Path.GetFileNameWithoutExtension(importer.assetPath),
dirName
);
importer.SafeCreateDirectory(path);
Dictionary<VrmLib.ImageTexture, string> targetPaths = new Dictionary<VrmLib.ImageTexture, string>();
// Reload Model
var model = CreateModel(importer.assetPath);
var mimeTypeReg = new System.Text.RegularExpressions.Regex("image/(?<mime>.*)$");
int count = 0;
foreach (var texture in model.Textures)
{
var imageTexture = texture as VrmLib.ImageTexture;
if (imageTexture == null) continue;
var mimeType = mimeTypeReg.Match(imageTexture.Image.MimeType);
var assetName = !string.IsNullOrEmpty(imageTexture.Name) ? imageTexture.Name : string.Format("{0}_img{1}", model.Root.Name, count);
var targetPath = string.Format("{0}/{1}.{2}",
path,
assetName,
mimeType.Groups["mime"].Value);
imageTexture.Name = assetName;
if (imageTexture.TextureType == VrmLib.Texture.TextureTypes.MetallicRoughness
|| imageTexture.TextureType == VrmLib.Texture.TextureTypes.Occlusion)
{
var subAssetTexture = subAssets.Where(x => x.name == imageTexture.Name).FirstOrDefault();
File.WriteAllBytes(targetPath, subAssetTexture.EncodeToPNG());
}
else
{
File.WriteAllBytes(targetPath, imageTexture.Image.Bytes.ToArray());
}
AssetDatabase.ImportAsset(targetPath);
targetPaths.Add(imageTexture, targetPath);
count++;
}
EditorApplication.delayCall += () =>
{
foreach (var targetPath in targetPaths)
{
var imageTexture = targetPath.Key;
var targetTextureImporter = AssetImporter.GetAtPath(targetPath.Value) as TextureImporter;
targetTextureImporter.sRGBTexture = (imageTexture.ColorSpace == VrmLib.Texture.ColorSpaceTypes.Srgb);
if (imageTexture.TextureType == VrmLib.Texture.TextureTypes.NormalMap)
{
targetTextureImporter.textureType = TextureImporterType.NormalMap;
}
targetTextureImporter.SaveAndReimport();
var externalObject = AssetDatabase.LoadAssetAtPath(targetPath.Value, typeof(UnityEngine.Texture2D));
importer.AddRemap(new AssetImporter.SourceAssetIdentifier(typeof(UnityEngine.Texture2D), imageTexture.Name), externalObject);
}
//AssetDatabase.WriteImportSettingsIfDirty(assetPath);
AssetDatabase.ImportAsset(importer.assetPath, ImportAssetOptions.ForceUpdate);
if (onComplited != null)
{
onComplited();
}
};
}
public static DirectoryInfo SafeCreateDirectory(this ScriptedImporter importer, string path)
{
if (Directory.Exists(path))
{
return null;
}
return Directory.CreateDirectory(path);
}
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: eb950c51864585a4688048266e6c3a00
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,221 +1,22 @@
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEditor;
#if UNITY_2020_2_OR_NEWER
#if UNITY_2020_2_OR_NEWER
using UnityEditor.AssetImporters;
#else
using UnityEditor.Experimental.AssetImporters;
using UnityEngine;
#endif
namespace UniVRM10
{
[ScriptedImporter(1, "vrm")]
public class VrmScriptedImporter : ScriptedImporter, IExternalUnityObject
public class VrmScriptedImporter : ScriptedImporter
{
const string TextureDirName = "Textures";
const string MaterialDirName = "Materials";
const string MetaDirName = "MetaObjects";
const string ExpressionDirName = "Expressions";
[SerializeField]
public bool MigrateToVrm1 = default;
public override void OnImportAsset(AssetImportContext ctx)
{
Debug.Log("OnImportAsset to " + ctx.assetPath);
try
{
// Create Vrm Model
VrmLib.Model model = VrmLoader.CreateVrmModel(ctx.assetPath);
if (model == null)
{
// maybe VRM-0.X
return;
}
Debug.Log($"VrmLoader.CreateVrmModel: {model}");
// Build Unity Model
var assets = EditorUnityBuilder.ToUnityAsset(model, assetPath, this);
ComponentBuilder.Build10(model, assets);
// Texture
var externalTextures = this.GetExternalUnityObjects<UnityEngine.Texture2D>();
foreach (var texture in assets.Textures)
{
if (texture == null)
continue;
if (externalTextures.ContainsValue(texture))
{
}
else
{
ctx.AddObjectToAsset(texture.name, texture);
}
}
// Material
var externalMaterials = this.GetExternalUnityObjects<UnityEngine.Material>();
foreach (var material in assets.Materials)
{
if (material == null)
continue;
if (externalMaterials.ContainsValue(material))
{
}
else
{
ctx.AddObjectToAsset(material.name, material);
}
}
// Mesh
foreach (var mesh in assets.Meshes)
{
ctx.AddObjectToAsset(mesh.name, mesh);
}
//// ScriptableObject
// avatar
ctx.AddObjectToAsset("avatar", assets.HumanoidAvatar);
// meta
{
var external = this.GetExternalUnityObjects<UniVRM10.VRM10MetaObject>().FirstOrDefault();
if (external.Value != null)
{
var controller = assets.Root.GetComponent<VRM10Controller>();
if (controller != null)
{
controller.Meta = external.Value;
}
}
else
{
var meta = assets.ScriptableObjects
.FirstOrDefault(x => x.GetType() == typeof(UniVRM10.VRM10MetaObject)) as UniVRM10.VRM10MetaObject;
if (meta != null)
{
meta.name = "meta";
ctx.AddObjectToAsset(meta.name, meta);
}
}
}
// expression
{
var external = this.GetExternalUnityObjects<UniVRM10.VRM10Expression>();
if (external.Any())
{
}
else
{
var expression = assets.ScriptableObjects
.Where(x => x.GetType() == typeof(UniVRM10.VRM10Expression))
.Select(x => x as UniVRM10.VRM10Expression);
foreach (var clip in expression)
{
clip.name = clip.ExpressionName;
ctx.AddObjectToAsset(clip.ExpressionName, clip);
}
}
}
{
var external = this.GetExternalUnityObjects<UniVRM10.VRM10ExpressionAvatar>().FirstOrDefault();
if (external.Value != null)
{
var controller = assets.Root.GetComponent<VRM10Controller>();
if (controller != null)
{
controller.Expression.ExpressionAvatar = external.Value;
}
}
else
{
var expressionAvatar = assets.ScriptableObjects
.FirstOrDefault(x => x.GetType() == typeof(UniVRM10.VRM10ExpressionAvatar)) as UniVRM10.VRM10ExpressionAvatar;
if (expressionAvatar != null)
{
expressionAvatar.name = "expressionAvatar";
ctx.AddObjectToAsset(expressionAvatar.name, expressionAvatar);
}
}
}
// Root
ctx.AddObjectToAsset(assets.Root.name, assets.Root);
ctx.SetMainObject(assets.Root);
}
catch (System.Exception ex)
{
Debug.LogError(ex);
}
}
public void ExtractTextures()
{
this.ExtractTextures(TextureDirName, (path) => { return VrmLoader.CreateVrmModel(path); });
AssetDatabase.ImportAsset(assetPath, ImportAssetOptions.ForceUpdate);
}
public void ExtractMaterials()
{
this.ExtractAssets<UnityEngine.Material>(MaterialDirName, ".mat");
AssetDatabase.ImportAsset(assetPath, ImportAssetOptions.ForceUpdate);
}
public void ExtractMaterialsAndTextures()
{
this.ExtractTextures(TextureDirName, (path) => { return VrmLoader.CreateVrmModel(path); }, () => { this.ExtractAssets<UnityEngine.Material>(MaterialDirName, ".mat"); });
AssetDatabase.ImportAsset(assetPath, ImportAssetOptions.ForceUpdate);
}
public void ExtractMeta()
{
this.ExtractAssets<UniVRM10.VRM10MetaObject>(MetaDirName, ".asset");
var metaObject = this.GetExternalUnityObjects<UniVRM10.VRM10MetaObject>().FirstOrDefault();
var metaObjectPath = AssetDatabase.GetAssetPath(metaObject.Value);
if (!string.IsNullOrEmpty(metaObjectPath))
{
EditorUtility.SetDirty(metaObject.Value);
AssetDatabase.WriteImportSettingsIfDirty(metaObjectPath);
}
AssetDatabase.ImportAsset(assetPath, ImportAssetOptions.ForceUpdate);
}
public void ExtractExpressions()
{
this.ExtractAssets<UniVRM10.VRM10ExpressionAvatar>(ExpressionDirName, ".asset");
this.ExtractAssets<UniVRM10.VRM10Expression>(ExpressionDirName, ".asset");
var expressionAvatar = this.GetExternalUnityObjects<UniVRM10.VRM10ExpressionAvatar>().FirstOrDefault();
var expressions = this.GetExternalUnityObjects<UniVRM10.VRM10Expression>();
expressionAvatar.Value.Clips = expressions.Select(x => x.Value).ToList();
var avatarPath = AssetDatabase.GetAssetPath(expressionAvatar.Value);
if (!string.IsNullOrEmpty(avatarPath))
{
EditorUtility.SetDirty(expressionAvatar.Value);
AssetDatabase.WriteImportSettingsIfDirty(avatarPath);
}
AssetDatabase.ImportAsset(assetPath, ImportAssetOptions.ForceUpdate);
}
public Dictionary<string, T> GetExternalUnityObjects<T>() where T : UnityEngine.Object
{
return this.GetExternalObjectMap().Where(x => x.Key.type == typeof(T)).ToDictionary(x => x.Key.name, x => (T)x.Value);
}
public void SetExternalUnityObject<T>(UnityEditor.AssetImporter.SourceAssetIdentifier sourceAssetIdentifier, T obj) where T : UnityEngine.Object
{
this.AddRemap(sourceAssetIdentifier, obj);
AssetDatabase.WriteImportSettingsIfDirty(this.assetPath);
AssetDatabase.ImportAsset(this.assetPath, ImportAssetOptions.ForceUpdate);
VrmScriptedImporterImpl.Import(this, ctx, MigrateToVrm1);
}
}
}
}

View File

@@ -1,6 +1,7 @@
using System.Linq;
using UnityEditor;
using UnityEngine;
using UniGLTF;
#if UNITY_2020_2_OR_NEWER
using UnityEditor.AssetImporters;
#else
@@ -13,91 +14,140 @@ namespace UniVRM10
[CustomEditor(typeof(VrmScriptedImporter))]
public class VrmScriptedImporterEditorGUI : ScriptedImporterEditor
{
// const string TextureDirName = "Textures";
// const string MaterialDirName = "Materials";
// const string MetaDirName = "MetaObjects";
// const string ExpressionDirName = "Expressions";
private bool _isOpen = true;
VrmScriptedImporter m_importer;
GltfParser m_parser;
VrmLib.Model m_model;
public override void OnEnable()
{
base.OnEnable();
m_importer = target as VrmScriptedImporter;
m_parser = VrmScriptedImporterImpl.Parse(m_importer.assetPath, m_importer.MigrateToVrm1);
if (m_parser == null)
{
return;
}
m_model = VrmLoader.CreateVrmModel(m_parser);
}
enum Tabs
{
Model,
Materials,
Vrm,
}
static Tabs s_currentTab;
public override void OnInspectorGUI()
{
var importer = target as VrmScriptedImporter;
s_currentTab = MeshUtility.TabBar.OnGUI(s_currentTab);
GUILayout.Space(10);
EditorGUILayout.LabelField("Extract settings");
switch (s_currentTab)
{
case Tabs.Model:
base.OnInspectorGUI();
break;
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel("Materials And Textures");
GUI.enabled = !(importer.GetExternalUnityObjects<UnityEngine.Material>().Any()
&& importer.GetExternalUnityObjects<UnityEngine.Texture2D>().Any());
if (GUILayout.Button("Extract"))
{
importer.ExtractMaterialsAndTextures();
}
GUI.enabled = !GUI.enabled;
if (GUILayout.Button("Clear"))
{
importer.ClearExternalObjects<UnityEngine.Material>();
importer.ClearExternalObjects<UnityEngine.Texture2D>();
}
GUI.enabled = true;
EditorGUILayout.EndHorizontal();
case Tabs.Materials:
if (m_parser != null)
{
EditorMaterial.OnGUIMaterial(m_importer, m_parser, Vrm10MToonMaterialImporter.EnumerateAllTexturesDistinct);
}
break;
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel("Meta");
GUI.enabled = !importer.GetExternalUnityObjects<UniVRM10.VRM10MetaObject>().Any();
if (GUILayout.Button("Extract"))
{
importer.ExtractMeta();
case Tabs.Vrm:
break;
}
GUI.enabled = !GUI.enabled;
if (GUILayout.Button("Clear"))
{
importer.ClearExternalObjects<UniVRM10.VRM10MetaObject>();
}
GUI.enabled = true;
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel("Expressions");
GUI.enabled = !(importer.GetExternalUnityObjects<UniVRM10.VRM10ExpressionAvatar>().Any()
&& importer.GetExternalUnityObjects<UniVRM10.VRM10Expression>().Any());
if (GUILayout.Button("Extract"))
{
importer.ExtractExpressions();
}
GUI.enabled = !GUI.enabled;
if (GUILayout.Button("Clear"))
{
importer.ClearExternalObjects<UniVRM10.VRM10ExpressionAvatar>();
importer.ClearExternalObjects<UniVRM10.VRM10Expression>();
}
GUI.enabled = true;
EditorGUILayout.EndHorizontal();
// ObjectMap
DrawRemapGUI<UnityEngine.Material>("Material Remap", importer);
DrawRemapGUI<UnityEngine.Texture2D>("Texture Remap", importer);
DrawRemapGUI<UniVRM10.VRM10MetaObject>("Meta Remap", importer);
DrawRemapGUI<UniVRM10.VRM10ExpressionAvatar>("ExpressionAvatar Remap", importer);
DrawRemapGUI<UniVRM10.VRM10Expression>("Expression Remap", importer);
base.OnInspectorGUI();
}
private void DrawRemapGUI<T>(string title, VrmScriptedImporter importer) where T : UnityEngine.Object
{
EditorGUILayout.Foldout(_isOpen, title);
EditorGUI.indentLevel++;
var objects = importer.GetExternalObjectMap().Where(x => x.Key.type == typeof(T));
foreach (var obj in objects)
{
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel(obj.Key.name);
var asset = EditorGUILayout.ObjectField(obj.Value, obj.Key.type, true) as T;
if (asset != obj.Value)
{
importer.SetExternalUnityObject(obj.Key, asset);
}
EditorGUILayout.EndHorizontal();
}
EditorGUI.indentLevel--;
}
// var importer = target as VrmScriptedImporter;
// EditorGUILayout.LabelField("Extract settings");
// EditorGUILayout.BeginHorizontal();
// EditorGUILayout.PrefixLabel("Materials And Textures");
// GUI.enabled = !(importer.GetExternalUnityObjects<UnityEngine.Material>().Any()
// && importer.GetExternalUnityObjects<UnityEngine.Texture2D>().Any());
// if (GUILayout.Button("Extract"))
// {
// importer.ExtractMaterialsAndTextures();
// }
// GUI.enabled = !GUI.enabled;
// if (GUILayout.Button("Clear"))
// {
// importer.ClearExternalObjects<UnityEngine.Material>();
// importer.ClearExternalObjects<UnityEngine.Texture2D>();
// }
// GUI.enabled = true;
// EditorGUILayout.EndHorizontal();
// EditorGUILayout.BeginHorizontal();
// EditorGUILayout.PrefixLabel("Meta");
// GUI.enabled = !importer.GetExternalUnityObjects<UniVRM10.VRM10MetaObject>().Any();
// if (GUILayout.Button("Extract"))
// {
// importer.ExtractMeta();
// }
// GUI.enabled = !GUI.enabled;
// if (GUILayout.Button("Clear"))
// {
// importer.ClearExternalObjects<UniVRM10.VRM10MetaObject>();
// }
// GUI.enabled = true;
// EditorGUILayout.EndHorizontal();
// EditorGUILayout.BeginHorizontal();
// EditorGUILayout.PrefixLabel("Expressions");
// GUI.enabled = !(importer.GetExternalUnityObjects<UniVRM10.VRM10ExpressionAvatar>().Any()
// && importer.GetExternalUnityObjects<UniVRM10.VRM10Expression>().Any());
// if (GUILayout.Button("Extract"))
// {
// importer.ExtractExpressions();
// }
// GUI.enabled = !GUI.enabled;
// if (GUILayout.Button("Clear"))
// {
// importer.ClearExternalObjects<UniVRM10.VRM10ExpressionAvatar>();
// importer.ClearExternalObjects<UniVRM10.VRM10Expression>();
// }
// GUI.enabled = true;
// EditorGUILayout.EndHorizontal();
// // ObjectMap
// DrawRemapGUI<UnityEngine.Material>("Material Remap", importer);
// DrawRemapGUI<UnityEngine.Texture2D>("Texture Remap", importer);
// DrawRemapGUI<UniVRM10.VRM10MetaObject>("Meta Remap", importer);
// DrawRemapGUI<UniVRM10.VRM10ExpressionAvatar>("ExpressionAvatar Remap", importer);
// DrawRemapGUI<UniVRM10.VRM10Expression>("Expression Remap", importer);
// base.OnInspectorGUI();
// }
// private void DrawRemapGUI<T>(string title, VrmScriptedImporter importer) where T : UnityEngine.Object
// {
// EditorGUILayout.Foldout(_isOpen, title);
// EditorGUI.indentLevel++;
// var objects = importer.GetExternalObjectMap().Where(x => x.Key.type == typeof(T));
// foreach (var obj in objects)
// {
// EditorGUILayout.BeginHorizontal();
// EditorGUILayout.PrefixLabel(obj.Key.name);
// var asset = EditorGUILayout.ObjectField(obj.Value, obj.Key.type, true) as T;
// if (asset != obj.Value)
// {
// importer.SetExternalUnityObject(obj.Key, asset);
// }
// EditorGUILayout.EndHorizontal();
// }
// EditorGUI.indentLevel--;
// }
}
}

View File

@@ -0,0 +1,208 @@
using System.Linq;
using UnityEngine;
using UniGLTF;
using System.IO;
#if UNITY_2020_2_OR_NEWER
using UnityEditor.AssetImporters;
#else
using UnityEditor.Experimental.AssetImporters;
#endif
namespace UniVRM10
{
public static class VrmScriptedImporterImpl
{
/// <summary>
/// VRM1 で パースし、失敗したら Migration してから VRM1 でパースする
/// </summary>
/// <param name="path"></param>
/// <param name="migrateToVrm1"></param>
/// <returns></returns>
public static GltfParser Parse(string path, bool migrateToVrm1)
{
//
// Parse(parse glb, parser gltf json)
//
var parser = new GltfParser();
parser.ParsePath(path);
if (UniGLTF.Extensions.VRMC_vrm.GltfDeserializer.TryGet(parser.GLTF.extensions, out UniGLTF.Extensions.VRMC_vrm.VRMC_vrm vrm))
{
return parser;
}
if (migrateToVrm1)
{
// try migrateion
var migrated = MigrationVrm.Migrate(File.ReadAllBytes(path));
parser = new GltfParser();
parser.Parse(path, migrated);
return parser;
}
return null;
}
public static void Import(ScriptedImporter scriptedImporter, AssetImportContext context, bool migrateToVrm1)
{
#if VRM_DEVELOP
Debug.Log("OnImportAsset to " + scriptedImporter.assetPath);
#endif
var parser = Parse(scriptedImporter.assetPath, migrateToVrm1);
if (parser == null)
{
// fail to parse vrm1
return;
}
//
// Import(create unity objects)
//
var externalObjectMap = scriptedImporter.GetExternalObjectMap().Select(kv => (kv.Value.name, kv.Value)).ToArray();
using (var loader = new RuntimeUnityBuilder(parser, externalObjectMap))
{
// settings TextureImporters
foreach (var textureInfo in Vrm10MToonMaterialImporter.EnumerateAllTexturesDistinct(parser))
{
TextureImporterConfigurator.Configure(textureInfo, loader.TextureFactory.ExternalMap);
}
loader.Load();
loader.ShowMeshes();
loader.TransferOwnership(o =>
{
context.AddObjectToAsset(o.name, o);
if (o is GameObject)
{
// Root GameObject is main object
context.SetMainObject(loader.Root);
}
return true;
});
}
}
// public void ExtractMeta()
// {
// this.ExtractAssets<UniVRM10.VRM10MetaObject>(MetaDirName, ".asset");
// var metaObject = this.GetExternalUnityObjects<UniVRM10.VRM10MetaObject>().FirstOrDefault();
// var metaObjectPath = AssetDatabase.GetAssetPath(metaObject.Value);
// if (!string.IsNullOrEmpty(metaObjectPath))
// {
// EditorUtility.SetDirty(metaObject.Value);
// AssetDatabase.WriteImportSettingsIfDirty(metaObjectPath);
// }
// AssetDatabase.ImportAsset(assetPath, ImportAssetOptions.ForceUpdate);
// }
// public void ExtractExpressions()
// {
// this.ExtractAssets<UniVRM10.VRM10ExpressionAvatar>(ExpressionDirName, ".asset");
// this.ExtractAssets<UniVRM10.VRM10Expression>(ExpressionDirName, ".asset");
// var expressionAvatar = this.GetExternalUnityObjects<UniVRM10.VRM10ExpressionAvatar>().FirstOrDefault();
// var expressions = this.GetExternalUnityObjects<UniVRM10.VRM10Expression>();
// expressionAvatar.Value.Clips = expressions.Select(x => x.Value).ToList();
// var avatarPath = AssetDatabase.GetAssetPath(expressionAvatar.Value);
// if (!string.IsNullOrEmpty(avatarPath))
// {
// EditorUtility.SetDirty(expressionAvatar.Value);
// AssetDatabase.WriteImportSettingsIfDirty(avatarPath);
// }
// AssetDatabase.ImportAsset(assetPath, ImportAssetOptions.ForceUpdate);
// }
// public Dictionary<string, T> GetExternalUnityObjects<T>() where T : UnityEngine.Object
// {
// return this.GetExternalObjectMap().Where(x => x.Key.type == typeof(T)).ToDictionary(x => x.Key.name, x => (T)x.Value);
// }
// public void SetExternalUnityObject<T>(UnityEditor.AssetImporter.SourceAssetIdentifier sourceAssetIdentifier, T obj) where T : UnityEngine.Object
// {
// this.AddRemap(sourceAssetIdentifier, obj);
// AssetDatabase.WriteImportSettingsIfDirty(this.assetPath);
// AssetDatabase.ImportAsset(this.assetPath, ImportAssetOptions.ForceUpdate);
// }
// public static void ClearExternalObjects<T>(this ScriptedImporter importer) where T : UnityEngine.Object
// {
// foreach (var extarnalObject in importer.GetExternalObjectMap().Where(x => x.Key.type == typeof(T)))
// {
// importer.RemoveRemap(extarnalObject.Key);
// }
// AssetDatabase.WriteImportSettingsIfDirty(importer.assetPath);
// AssetDatabase.ImportAsset(importer.assetPath, ImportAssetOptions.ForceUpdate);
// }
// public static void ClearExtarnalObjects(this ScriptedImporter importer)
// {
// foreach (var extarnalObject in importer.GetExternalObjectMap())
// {
// importer.RemoveRemap(extarnalObject.Key);
// }
// AssetDatabase.WriteImportSettingsIfDirty(importer.assetPath);
// AssetDatabase.ImportAsset(importer.assetPath, ImportAssetOptions.ForceUpdate);
// }
// private static T GetSubAsset<T>(this ScriptedImporter importer, string assetPath) where T : UnityEngine.Object
// {
// return importer.GetSubAssets<T>(assetPath)
// .FirstOrDefault();
// }
// public static IEnumerable<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);
// }
// private static void ExtractFromAsset(UnityEngine.Object subAsset, string destinationPath, bool isForceUpdate)
// {
// string assetPath = AssetDatabase.GetAssetPath(subAsset);
// var clone = UnityEngine.Object.Instantiate(subAsset);
// AssetDatabase.CreateAsset(clone, destinationPath);
// var assetImporter = AssetImporter.GetAtPath(assetPath);
// assetImporter.AddRemap(new AssetImporter.SourceAssetIdentifier(subAsset), clone);
// if (isForceUpdate)
// {
// AssetDatabase.WriteImportSettingsIfDirty(assetPath);
// AssetDatabase.ImportAsset(assetPath, ImportAssetOptions.ForceUpdate);
// }
// }
// public static void ExtractAssets<T>(this ScriptedImporter importer, string dirName, string extension) where T : UnityEngine.Object
// {
// if (string.IsNullOrEmpty(importer.assetPath))
// return;
// var subAssets = importer.GetSubAssets<T>(importer.assetPath);
// var path = string.Format("{0}/{1}.{2}",
// Path.GetDirectoryName(importer.assetPath),
// Path.GetFileNameWithoutExtension(importer.assetPath),
// dirName
// );
// var info = importer.SafeCreateDirectory(path);
// foreach (var asset in subAssets)
// {
// ExtractFromAsset(asset, string.Format("{0}/{1}{2}", path, asset.name, extension), false);
// }
// }
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 35c90d5d3fa706b4f87a92ce4dc59008
guid: f08e514e6a60bd0479ed1c928e8b515e
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -6,7 +6,8 @@
"MeshUtility",
"MeshUtility.Editor",
"UniGLTF.Editor",
"UniGLTF"
"UniGLTF",
"VRMShaders"
],
"optionalUnityReferences": [],
"includePlatforms": [

View File

@@ -135,7 +135,7 @@ namespace UniVRM10
{
return ("", MessageType.None);
});
m_reference = new ValidateProperty(serializedObject.FindProperty(nameof(m_target.Reference)), prop =>
m_reference = new ValidateProperty(serializedObject.FindProperty(nameof(m_target.References)), prop =>
{
return ("", MessageType.None);
});

View File

@@ -68,7 +68,7 @@ namespace UniVRM10
Selection.selectionChanged += Repaint;
m_tmpMeta = ScriptableObject.CreateInstance<VRM10MetaObject>();
m_tmpMeta.Authors = new string[] { "" };
m_tmpMeta.Authors = new List<string> { "" };
m_state = new MeshUtility.ExporterDialogState();
m_state.ExportRootChanged += (root) =>

View File

@@ -7,7 +7,7 @@ namespace UniVRM10
/// FreezeAxesで使う。bitマスク
/// </summary>
[Flags]
public enum AxesMask
public enum AxisMask
{
X = 1,
Y = 2,
@@ -16,17 +16,17 @@ namespace UniVRM10
public static class AxesMaskExtensions
{
public static Vector3 Freeze(this AxesMask mask, Vector3 src)
public static Vector3 Freeze(this AxisMask mask, Vector3 src)
{
if (mask.HasFlag(AxesMask.X))
if (mask.HasFlag(AxisMask.X))
{
src.x = 0;
}
if (mask.HasFlag(AxesMask.Y))
if (mask.HasFlag(AxisMask.Y))
{
src.y = 0;
}
if (mask.HasFlag(AxesMask.Z))
if (mask.HasFlag(AxisMask.Z))
{
src.z = 0;
}

View File

@@ -1,33 +1,28 @@
using System;
using UniGLTF.Extensions.VRMC_constraints;
using UnityEngine;
namespace UniVRM10
{
public enum DestinationCoordinates
{
World,
Local,
}
class ConstraintDestination
{
readonly Transform m_transform;
readonly DestinationCoordinates m_coords;
readonly ObjectSpace m_coords;
readonly TRS m_initial;
public ConstraintDestination(Transform t, DestinationCoordinates coords)
public ConstraintDestination(Transform t, ObjectSpace coords)
{
m_transform = t;
m_coords = coords;
switch (m_coords)
{
case DestinationCoordinates.World:
m_initial = TRS.GetWorld(t);
break;
// case ObjectSpace.World:
// m_initial = TRS.GetWorld(t);
// break;
case DestinationCoordinates.Local:
case ObjectSpace.local:
m_initial = TRS.GetLocal(t);
break;
@@ -41,11 +36,11 @@ namespace UniVRM10
var value = m_initial.Translation + delta * weight;
switch (m_coords)
{
case DestinationCoordinates.World:
m_transform.position = value;
break;
// case DestinationCoordinates.World:
// m_transform.position = value;
// break;
case DestinationCoordinates.Local:
case ObjectSpace.local:
m_transform.localPosition = value;
break;
@@ -60,11 +55,11 @@ namespace UniVRM10
var value = Quaternion.LerpUnclamped(Quaternion.identity, delta, weight) * m_initial.Rotation;
switch (m_coords)
{
case DestinationCoordinates.World:
m_transform.rotation = value;
break;
// case DestinationCoordinates.World:
// m_transform.rotation = value;
// break;
case DestinationCoordinates.Local:
case ObjectSpace.local:
m_transform.localRotation = value;
break;

View File

@@ -1,33 +1,16 @@
using UnityEngine;
using System;
using UniGLTF.Extensions.VRMC_constraints;
namespace UniVRM10
{
public enum SourceCoordinates
{
/// <summary>
/// ワールド座標
/// </summary>
World,
/// <summary>
/// モデルルート(指定のTransform)ローカル座標
/// </summary>
Model,
/// <summary>
/// m_transform ローカル座標
/// </summary>
Local,
}
class ConstraintSource
{
readonly Transform m_modelRoot;
readonly Transform m_transform;
readonly SourceCoordinates m_coords;
readonly ObjectSpace m_coords;
readonly TRS m_initial;
@@ -37,9 +20,9 @@ namespace UniVRM10
{
switch (m_coords)
{
case SourceCoordinates.World: return m_transform.position - m_initial.Translation;
case SourceCoordinates.Local: return m_transform.localPosition - m_initial.Translation;
case SourceCoordinates.Model: return m_modelRoot.worldToLocalMatrix.MultiplyPoint(m_transform.position) - m_initial.Translation;
// case ObjectSpace.World: return m_transform.position - m_initial.Translation;
case ObjectSpace.local: return m_transform.localPosition - m_initial.Translation;
case ObjectSpace.model: return m_modelRoot.worldToLocalMatrix.MultiplyPoint(m_transform.position) - m_initial.Translation;
default: throw new NotImplementedException();
}
}
@@ -52,30 +35,30 @@ namespace UniVRM10
switch (m_coords)
{
// 右からかけるか、左からかけるか、それが問題なのだ
case SourceCoordinates.World: return m_transform.rotation * Quaternion.Inverse(m_initial.Rotation);
case SourceCoordinates.Local: return m_transform.localRotation * Quaternion.Inverse(m_initial.Rotation);
case SourceCoordinates.Model: return m_transform.rotation * Quaternion.Inverse(m_modelRoot.rotation) * Quaternion.Inverse(m_initial.Rotation);
// case SourceCoordinates.World: return m_transform.rotation * Quaternion.Inverse(m_initial.Rotation);
case ObjectSpace.local: return m_transform.localRotation * Quaternion.Inverse(m_initial.Rotation);
case ObjectSpace.model: return m_transform.rotation * Quaternion.Inverse(m_modelRoot.rotation) * Quaternion.Inverse(m_initial.Rotation);
default: throw new NotImplementedException();
}
}
}
public ConstraintSource(Transform t, SourceCoordinates coords, Transform modelRoot = null)
public ConstraintSource(Transform t, ObjectSpace coords, Transform modelRoot = null)
{
m_transform = t;
m_coords = coords;
switch (coords)
{
case SourceCoordinates.World:
m_initial = TRS.GetWorld(t);
break;
// case SourceCoordinates.World:
// m_initial = TRS.GetWorld(t);
// break;
case SourceCoordinates.Local:
case ObjectSpace.local:
m_initial = TRS.GetLocal(t);
break;
case SourceCoordinates.Model:
case ObjectSpace.model:
{
var world = TRS.GetWorld(t);
m_modelRoot = modelRoot;

View File

@@ -11,10 +11,10 @@ namespace UniVRM10
///
/// </summary>
[DisallowMultipleComponent]
public class VRMAimConstraint : VRMConstraint
public class VRM10AimConstraint : VRM10Constraint
{
[SerializeField]
Transform Source = default;
public Transform Source = default;
// [SerializeField]
// [Range(0, 10.0f)]
@@ -24,12 +24,13 @@ namespace UniVRM10
/// Forward
/// </summary>
[SerializeField]
Vector3 AimVector = Vector3.forward;
public Vector3 AimVector = Vector3.forward;
[SerializeField]
Vector3 UpVector = Vector3.up;
public Vector3 UpVector = Vector3.up;
Vector3 RightVector;
[SerializeField]
public Vector3 RightVector;
Quaternion m_selfInitial;
Matrix4x4 m_coords;

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e1e8c3a00191fbd4db98fb47ddb80e8c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -2,7 +2,7 @@ using UnityEngine;
namespace UniVRM10
{
public abstract class VRMConstraint : MonoBehaviour
public abstract class VRM10Constraint : MonoBehaviour
{
public virtual void Process()
{

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ded8c4db12c688b46814cf0bf925cacf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,4 +1,5 @@
using UnityEngine;
using UniGLTF.Extensions.VRMC_constraints;
using UnityEngine;
namespace UniVRM10
{
@@ -6,26 +7,26 @@ namespace UniVRM10
/// 対象の初期位置と現在位置の差分(delta)を、自身の初期位置に対してWeightを乗算して加算する。
/// </summary>
[DisallowMultipleComponent]
public class VRMPositionConstraint : VRMConstraint
public class VRM10PositionConstraint : VRM10Constraint
{
[SerializeField]
Transform Source = default;
public Transform Source = default;
[SerializeField]
SourceCoordinates SourceCoordinate = default;
public ObjectSpace SourceCoordinate = default;
[SerializeField]
DestinationCoordinates DestinationCoordinate = default;
public ObjectSpace DestinationCoordinate = default;
[SerializeField]
AxesMask FreezeAxes = default;
public AxisMask FreezeAxes = default;
[SerializeField]
[Range(0, 10.0f)]
float Weight = 1.0f;
public float Weight = 1.0f;
[SerializeField]
Transform ModelRoot = default;
public Transform ModelRoot = default;
ConstraintSource m_src;

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6fec0847a81b2124c9f67575d247b1f9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,4 +1,5 @@
using UnityEngine;
using UniGLTF.Extensions.VRMC_constraints;
using UnityEngine;
namespace UniVRM10
@@ -7,26 +8,26 @@ namespace UniVRM10
/// 対象の初期回転と現在回転の差分(delta)を、自身の初期回転と自身の初期回転にdeltaを乗算したものに対してWeightでSlerpする。
/// </summary>
[DisallowMultipleComponent]
public class VRMRotationConstraint : VRMConstraint
public class VRM10RotationConstraint : VRM10Constraint
{
[SerializeField]
Transform Source = default;
public Transform Source = default;
[SerializeField]
SourceCoordinates SourceCoordinate = default;
public ObjectSpace SourceCoordinate = default;
[SerializeField]
DestinationCoordinates DestinationCoordinate = default;
public ObjectSpace DestinationCoordinate = default;
[SerializeField]
AxesMask FreezeAxes = default;
public AxisMask FreezeAxes = default;
[SerializeField]
[Range(0, 10.0f)]
float Weight = 1.0f;
public float Weight = 1.0f;
[SerializeField]
Transform ModelRoot = default;
public Transform ModelRoot = default;
ConstraintSource m_src;

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7a07fbecedce41b4396f286fd7634e1d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: a8f13bc2bb7b6734e92bba2b204e2e49
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: e017e9a63d31c4e4cbcc905a0caf0605
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 0f104dcf447611a4ca99f4ac41e806e8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: e7e95091802973e488fdcc4b3840cdc5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UniGLTF.Extensions.VRMC_vrm;
using UnityEngine;
using VrmLib;
@@ -88,11 +89,11 @@ namespace UniVRM10
{
switch (type)
{
case ExpressionOverrideType.None:
case ExpressionOverrideType.none:
return 0f;
case ExpressionOverrideType.Block:
case ExpressionOverrideType.block:
return weight > 0f ? 1f : 0f;
case ExpressionOverrideType.Blend:
case ExpressionOverrideType.blend:
return weight;
default:
throw new ArgumentOutOfRangeException(nameof(type), type, null);

View File

@@ -9,8 +9,8 @@ namespace UniVRM10
/// <summary>
/// Enum.ToString() のGC回避用キャッシュ
/// </summary>
private static readonly Dictionary<VrmLib.ExpressionPreset, string> PresetNameDictionary =
new Dictionary<VrmLib.ExpressionPreset, string>();
private static readonly Dictionary<UniGLTF.Extensions.VRMC_vrm.ExpressionPreset, string> PresetNameDictionary =
new Dictionary<UniGLTF.Extensions.VRMC_vrm.ExpressionPreset, string>();
/// <summary>
/// ExpressionPreset と同名の名前を持つ独自に追加した Expression を区別するための prefix
@@ -20,7 +20,7 @@ namespace UniVRM10
/// <summary>
/// Preset of this ExpressionKey.
/// </summary>
public readonly VrmLib.ExpressionPreset Preset;
public readonly UniGLTF.Extensions.VRMC_vrm.ExpressionPreset Preset;
/// <summary>
/// Custom Name of this ExpressionKey.
@@ -39,9 +39,9 @@ namespace UniVRM10
{
switch (Preset)
{
case VrmLib.ExpressionPreset.Blink:
case VrmLib.ExpressionPreset.BlinkLeft:
case VrmLib.ExpressionPreset.BlinkRight:
case UniGLTF.Extensions.VRMC_vrm.ExpressionPreset.blink:
case UniGLTF.Extensions.VRMC_vrm.ExpressionPreset.blinkLeft:
case UniGLTF.Extensions.VRMC_vrm.ExpressionPreset.blinkRight:
return true;
}
return false;
@@ -54,10 +54,10 @@ namespace UniVRM10
{
switch (Preset)
{
case VrmLib.ExpressionPreset.LookUp:
case VrmLib.ExpressionPreset.LookDown:
case VrmLib.ExpressionPreset.LookLeft:
case VrmLib.ExpressionPreset.LookRight:
case UniGLTF.Extensions.VRMC_vrm.ExpressionPreset.lookUp:
case UniGLTF.Extensions.VRMC_vrm.ExpressionPreset.lookDown:
case UniGLTF.Extensions.VRMC_vrm.ExpressionPreset.lookLeft:
case UniGLTF.Extensions.VRMC_vrm.ExpressionPreset.lookRight:
return true;
}
return false;
@@ -70,11 +70,11 @@ namespace UniVRM10
{
switch (Preset)
{
case VrmLib.ExpressionPreset.Aa:
case VrmLib.ExpressionPreset.Ih:
case VrmLib.ExpressionPreset.Ou:
case VrmLib.ExpressionPreset.Ee:
case VrmLib.ExpressionPreset.Oh:
case UniGLTF.Extensions.VRMC_vrm.ExpressionPreset.aa:
case UniGLTF.Extensions.VRMC_vrm.ExpressionPreset.ih:
case UniGLTF.Extensions.VRMC_vrm.ExpressionPreset.ou:
case UniGLTF.Extensions.VRMC_vrm.ExpressionPreset.ee:
case UniGLTF.Extensions.VRMC_vrm.ExpressionPreset.oh:
return true;
}
return false;
@@ -83,11 +83,11 @@ namespace UniVRM10
public bool IsProcedual => IsBlink || IsLookAt || IsMouth;
public ExpressionKey(VrmLib.ExpressionPreset preset, string customName = null)
public ExpressionKey(UniGLTF.Extensions.VRMC_vrm.ExpressionPreset preset, string customName = null)
{
Preset = preset;
if (Preset != VrmLib.ExpressionPreset.Custom)
if (Preset != UniGLTF.Extensions.VRMC_vrm.ExpressionPreset.custom)
{
if (PresetNameDictionary.ContainsKey((Preset)))
{
@@ -103,7 +103,7 @@ namespace UniVRM10
{
if (string.IsNullOrEmpty(customName))
{
throw new ArgumentException("name is required for VrmLib.ExpressionPreset.Custom");
throw new ArgumentException("name is required for UniGLTF.Extensions.VRMC_vrm.ExpressionPreset.Custom");
}
_id = $"{UnknownPresetPrefix}{customName}";
@@ -113,10 +113,10 @@ namespace UniVRM10
public static ExpressionKey CreateCustom(String key)
{
return new ExpressionKey(VrmLib.ExpressionPreset.Custom, key);
return new ExpressionKey(UniGLTF.Extensions.VRMC_vrm.ExpressionPreset.custom, key);
}
public static ExpressionKey CreateFromPreset(VrmLib.ExpressionPreset preset)
public static ExpressionKey CreateFromPreset(UniGLTF.Extensions.VRMC_vrm.ExpressionPreset preset)
{
return new ExpressionKey(preset);
}

View File

@@ -7,7 +7,7 @@ namespace UniVRM10
public struct MaterialColorBinding : IEquatable<MaterialColorBinding>
{
public String MaterialName;
public VrmLib.MaterialBindType BindType;
public UniGLTF.Extensions.VRMC_vrm.MaterialColorType BindType;
public Vector4 TargetValue;
public bool Equals(MaterialColorBinding other)

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using UniGLTF.Extensions.VRMC_vrm;
using UnityEngine;
namespace UniVRM10
@@ -9,6 +10,40 @@ namespace UniVRM10
///
internal sealed class MaterialValueBindingMerger
{
public const string UV_PROPERTY = "_MainTex_ST";
public const string COLOR_PROPERTY = "_Color";
public const string EMISSION_COLOR_PROPERTY = "_EmissionColor";
public const string RIM_COLOR_PROPERTY = "_RimColor";
public const string OUTLINE_COLOR_PROPERTY = "_OutlineColor";
public const string SHADE_COLOR_PROPERTY = "_ShadeColor";
public static string GetProperty(MaterialColorType bindType)
{
switch (bindType)
{
// case MaterialBindType.UvOffset:
// case MaterialBindType.UvScale:
// return UV_PROPERTY;
case MaterialColorType.color:
return COLOR_PROPERTY;
case MaterialColorType.emissionColor:
return EMISSION_COLOR_PROPERTY;
case MaterialColorType.shadeColor:
return SHADE_COLOR_PROPERTY;
case MaterialColorType.rimColor:
return RIM_COLOR_PROPERTY;
case MaterialColorType.outlineColor:
return OUTLINE_COLOR_PROPERTY;
}
throw new NotImplementedException();
}
#region MaterialMap
/// <summary>
/// MaterialValueBinding の対象になるマテリアルの情報を記録する
@@ -44,7 +79,7 @@ namespace UniVRM10
item = new PreviewMaterialItem(material);
m_materialMap.Add(binding.MaterialName, item);
}
var propName = VrmLib.MaterialBindTypeExtensions.GetProperty(binding.BindType);
var propName = GetProperty(binding.BindType);
item.PropMap.Add(binding.BindType, new PropItem
{
Name = propName,
@@ -179,7 +214,7 @@ namespace UniVRM10
return new MaterialTarget
{
MaterialName = binding.MaterialName,
ValueName = VrmLib.MaterialBindTypeExtensions.GetProperty(binding.BindType),
ValueName = GetProperty(binding.BindType),
};
}
}

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using UniGLTF.Extensions.VRMC_vrm;
#if UNITY_EDITOR
using UnityEditor;
#endif
@@ -57,7 +58,7 @@ namespace UniVRM10
Material = material;
}
public Dictionary<VrmLib.MaterialBindType, PropItem> PropMap = new Dictionary<VrmLib.MaterialBindType, PropItem>();
public Dictionary<UniGLTF.Extensions.VRMC_vrm.MaterialColorType, PropItem> PropMap = new Dictionary<UniGLTF.Extensions.VRMC_vrm.MaterialColorType, PropItem>();
public string[] PropNames
{
@@ -74,6 +75,35 @@ namespace UniVRM10
}
#if UNITY_EDITOR
public const string UV_PROPERTY = "_MainTex_ST";
public const string COLOR_PROPERTY = "_Color";
public const string EMISSION_COLOR_PROPERTY = "_EmissionColor";
public const string RIM_COLOR_PROPERTY = "_RimColor";
public const string OUTLINE_COLOR_PROPERTY = "_OutlineColor";
public const string SHADE_COLOR_PROPERTY = "_ShadeColor";
public static MaterialColorType GetBindType(string property)
{
switch (property)
{
case COLOR_PROPERTY:
return MaterialColorType.color;
case EMISSION_COLOR_PROPERTY:
return MaterialColorType.emissionColor;
case RIM_COLOR_PROPERTY:
return MaterialColorType.rimColor;
case SHADE_COLOR_PROPERTY:
return MaterialColorType.shadeColor;
case OUTLINE_COLOR_PROPERTY:
return MaterialColorType.outlineColor;
}
throw new NotImplementedException();
}
public static PreviewMaterialItem CreateForPreview(Material material)
{
var item = new PreviewMaterialItem(material);
@@ -89,7 +119,7 @@ namespace UniVRM10
case ShaderUtil.ShaderPropertyType.Color:
// 色
{
var bindType = VrmLib.MaterialBindTypeExtensions.GetBindType(name);
var bindType = GetBindType(name);
item.PropMap.Add(bindType, new PropItem
{
Name = name,

View File

@@ -53,7 +53,7 @@ namespace UniVRM10
/// ExpressionPreset を識別する。 Unknown の場合は、 ExpressionName で識別する
/// </summary>
[SerializeField]
public VrmLib.ExpressionPreset Preset;
public UniGLTF.Extensions.VRMC_vrm.ExpressionPreset Preset;
/// <summary>
/// 対象メッシュの Expression を操作する
@@ -83,19 +83,19 @@ namespace UniVRM10
/// この Expression と Blink(Blink, BlinkLeft, BlinkRight) が同時に有効な場合、Blink の Weight を 0 にする
/// </summary>
[SerializeField]
public VrmLib.ExpressionOverrideType OverrideBlink;
public UniGLTF.Extensions.VRMC_vrm.ExpressionOverrideType OverrideBlink;
/// <summary>
/// この Expression と LookAt(LookUp, LookDown, LookLeft, LookRight) が同時に有効な場合、LookAt の Weight を 0 にする
/// </summary>
[SerializeField]
public VrmLib.ExpressionOverrideType OverrideLookAt;
public UniGLTF.Extensions.VRMC_vrm.ExpressionOverrideType OverrideLookAt;
/// <summary>
/// この Expression と Mouth(Aa, Ih, Ou, Ee, Oh) が同時に有効な場合、Mouth の Weight を 0 にする
/// </summary>
[SerializeField]
public VrmLib.ExpressionOverrideType OverrideMouth;
public UniGLTF.Extensions.VRMC_vrm.ExpressionOverrideType OverrideMouth;
void Reset()
{
@@ -104,7 +104,7 @@ namespace UniVRM10
void OnValidate()
{
if (Preset == VrmLib.ExpressionPreset.Custom)
if (Preset == UniGLTF.Extensions.VRMC_vrm.ExpressionPreset.custom)
{
if (string.IsNullOrEmpty(ExpressionName))
{

View File

@@ -13,6 +13,8 @@ namespace UniVRM10
[CreateAssetMenu(menuName = "VRM10/ExpressionAvatar")]
public sealed class VRM10ExpressionAvatar : ScriptableObject
{
public const string ExtractKey = ".ExpressionAvatar";
[SerializeField]
public List<VRM10Expression> Clips = new List<VRM10Expression>();
@@ -79,15 +81,15 @@ namespace UniVRM10
/// </summary>
public void CreateDefaultPreset()
{
foreach (var preset in ((VrmLib.ExpressionPreset[])Enum.GetValues(typeof(VrmLib.ExpressionPreset)))
.Where(x => x != VrmLib.ExpressionPreset.Custom)
foreach (var preset in ((UniGLTF.Extensions.VRMC_vrm.ExpressionPreset[])Enum.GetValues(typeof(UniGLTF.Extensions.VRMC_vrm.ExpressionPreset)))
.Where(x => x != UniGLTF.Extensions.VRMC_vrm.ExpressionPreset.custom)
)
{
CreateDefaultPreset(preset);
}
}
void CreateDefaultPreset(VrmLib.ExpressionPreset preset)
void CreateDefaultPreset(UniGLTF.Extensions.VRMC_vrm.ExpressionPreset preset)
{
var clip = GetClip(new ExpressionKey(preset));
if (clip != null) return;

View File

@@ -7,7 +7,7 @@ namespace UniVRM10
public struct RendererFirstPersonFlags
{
public Renderer Renderer;
public VrmLib.FirstPersonMeshType FirstPersonFlag;
public UniGLTF.Extensions.VRMC_vrm.FirstPersonType FirstPersonFlag;
public Mesh SharedMesh
{
get

View File

@@ -31,20 +31,6 @@ namespace UniVRM10
}
}
public void Apply(VrmLib.LookAtRangeMap map)
{
CurveXRangeDegree = map.InputMaxValue;
CurveYRangeDegree = map.OutputScaling;
}
IEnumerable<Keyframe> ToKeys(float[] values)
{
for (int i = 0; i < values.Length; i += 4)
{
yield return new Keyframe(values[i], values[i + 1], values[i + 2], values[i + 3]);
}
}
public float Map(float src)
{
if (src < 0)

View File

@@ -1,6 +1,6 @@
using System.Collections.Generic;
using UniGLTF.Extensions.VRMC_vrm;
using UnityEngine;
using VrmLib;
namespace UniVRM10
{
@@ -10,12 +10,12 @@ namespace UniVRM10
private readonly CurveMapper _horizontalInner;
private readonly CurveMapper _verticalDown;
private readonly CurveMapper _verticalUp;
private readonly ExpressionKey _lookRightKey = ExpressionKey.CreateFromPreset(ExpressionPreset.LookRight);
private readonly ExpressionKey _lookLeftKey = ExpressionKey.CreateFromPreset(ExpressionPreset.LookLeft);
private readonly ExpressionKey _lookUpKey = ExpressionKey.CreateFromPreset(ExpressionPreset.LookUp);
private readonly ExpressionKey _lookDownKey = ExpressionKey.CreateFromPreset(ExpressionPreset.LookDown);
private readonly ExpressionKey _lookRightKey = ExpressionKey.CreateFromPreset(ExpressionPreset.lookRight);
private readonly ExpressionKey _lookLeftKey = ExpressionKey.CreateFromPreset(ExpressionPreset.lookLeft);
private readonly ExpressionKey _lookUpKey = ExpressionKey.CreateFromPreset(ExpressionPreset.lookUp);
private readonly ExpressionKey _lookDownKey = ExpressionKey.CreateFromPreset(ExpressionPreset.lookDown);
public LookAtEyeDirectionApplicableToExpression(
CurveMapper horizontalOuter, CurveMapper horizontalInner, CurveMapper verticalDown, CurveMapper verticalUp)
{
@@ -29,7 +29,7 @@ namespace UniVRM10
{
var yaw = eyeDirection.LeftYaw;
var pitch = eyeDirection.LeftPitch;
if (yaw < 0)
{
// Left

View File

@@ -10,6 +10,8 @@ namespace UniVRM10
[CreateAssetMenu(menuName = "VRM10/MetaObject")]
public class VRM10MetaObject : ScriptableObject
{
public const string ExtractKey = ".Meta";
[SerializeField]
public string ExporterVersion;
@@ -24,13 +26,13 @@ namespace UniVRM10
public string CopyrightInformation;
[SerializeField]
public string[] Authors;
public List<string> Authors = new List<string>();
[SerializeField]
public string ContactInformation;
[SerializeField]
public string Reference;
public List<string> References = new List<string>();
[SerializeField]
public Texture2D Thumbnail;
@@ -38,7 +40,7 @@ namespace UniVRM10
#region AvatarPermission
[SerializeField, Tooltip("A person who can perform with this avatar")]
public VrmLib.AvatarUsageType AllowedUser;
public UniGLTF.Extensions.VRMC_vrm.AvatarPermissionType AllowedUser;
[SerializeField, Tooltip("Violent acts using this avatar")]
public bool ViolentUsage;
@@ -47,7 +49,7 @@ namespace UniVRM10
public bool SexualUsage;
[SerializeField, Tooltip("For commercial use")]
public VrmLib.CommercialUsageType CommercialUsage;
public UniGLTF.Extensions.VRMC_vrm.CommercialUsageType CommercialUsage;
[SerializeField]
public bool GameUsage;
@@ -61,13 +63,13 @@ namespace UniVRM10
#region Distribution License
[SerializeField]
public VrmLib.CreditNotationType CreditNotation;
public UniGLTF.Extensions.VRMC_vrm.CreditNotationType CreditNotation;
[SerializeField]
public bool Redistribution;
[SerializeField]
public VrmLib.ModificationLicenseType ModificationLicense;
public UniGLTF.Extensions.VRMC_vrm.ModificationType ModificationLicense;
[SerializeField]
public string OtherLicenseUrl;
@@ -80,7 +82,7 @@ namespace UniVRM10
yield return Validation.Error("Require Name. ");
}
if (Authors == null || Authors.Length == 0)
if (Authors == null || Authors.Count == 0)
{
yield return Validation.Error("Require at leaset one Author.");
}
@@ -99,14 +101,14 @@ namespace UniVRM10
dst.CopyrightInformation = CopyrightInformation;
if (Authors != null)
{
dst.Authors = Authors.Select(x => x).ToArray();
dst.Authors = Authors.Select(x => x).ToList();
}
else
{
dst.Authors = new string[] { };
dst.Authors = new List<string>();
}
dst.ContactInformation = ContactInformation;
dst.Reference = Reference;
dst.References = References;
dst.Thumbnail = Thumbnail;
dst.AllowedUser = AllowedUser;
dst.ViolentUsage = ViolentUsage;

View File

@@ -13,7 +13,7 @@ namespace UniVRM10
public class VRM10SpringBone
{
[SerializeField]
public string m_comment;
public string Comment;
[SerializeField]
public List<VRM10SpringJoint> Joints = new List<VRM10SpringJoint>();

View File

@@ -47,27 +47,15 @@ namespace UniVRM10
[SerializeField]
public VRM10SpringBoneManager SpringBone = new VRM10SpringBoneManager();
[SerializeField]
public ModelAsset ModelAsset;
void OnDestroy()
{
if (Expression != null)
{
Expression.Restore();
}
if (ModelAsset != null)
{
#if UNITY_EDITOR
ModelAsset.DisposeEditor();
#else
ModelAsset.Dispose();
#endif
}
}
VRMConstraint[] m_constraints;
VRM10Constraint[] m_constraints;
Transform m_head;
public Transform Head
@@ -103,7 +91,7 @@ namespace UniVRM10
{
var animator = GetComponent<Animator>();
if (animator == null) return;
m_head = animator.GetBoneTransform(HumanBodyBones.Head);
LookAt.Setup(animator, m_head);
Expression.Setup(transform, LookAt, LookAt.EyeDirectionApplicable);
@@ -125,7 +113,7 @@ namespace UniVRM10
//
if (m_constraints == null)
{
m_constraints = GetComponentsInChildren<VRMConstraint>();
m_constraints = GetComponentsInChildren<VRM10Constraint>();
}
foreach (var constraint in m_constraints)
{
@@ -152,7 +140,7 @@ namespace UniVRM10
{
Setup();
}
private void Update()
{
if (Controller.UpdateType == VRM10ControllerImpl.UpdateTypes.Update)

View File

@@ -10,7 +10,7 @@ namespace UniVRM10
public sealed class VRM10ControllerExpression
{
public static IExpressionValidatorFactory ExpressionValidatorFactory = new DefaultExpressionValidator.Factory();
[SerializeField]
public VRM10ExpressionAvatar ExpressionAvatar;
@@ -30,17 +30,19 @@ namespace UniVRM10
public float BlinkOverrideRate { get; private set; }
public float LookAtOverrideRate { get; private set; }
public float MouthOverrideRate { get; private set; }
internal void Setup(Transform transform, ILookAtEyeDirectionProvider eyeDirectionProvider, ILookAtEyeDirectionApplicable eyeDirectionApplicable)
{
if (ExpressionAvatar == null)
{
Debug.LogError($"{nameof(VRM10ControllerExpression)}.{nameof(ExpressionAvatar)} is null.");
#if VRM_DEVELOP
Debug.LogWarning($"{nameof(VRM10ControllerExpression)}.{nameof(ExpressionAvatar)} is null.");
#endif
return;
}
Restore();
_merger = new ExpressionMerger(ExpressionAvatar.Clips, transform);
_keys = ExpressionAvatar.Clips.Select(ExpressionKey.CreateFromClip).ToList();
var oldInputWeights = _inputWeights;
@@ -55,12 +57,12 @@ namespace UniVRM10
_eyeDirectionProvider = eyeDirectionProvider;
_eyeDirectionApplicable = eyeDirectionApplicable;
}
internal void Restore()
{
_merger?.RestoreMaterialInitialValues();
_merger = null;
_eyeDirectionApplicable?.Restore();
_eyeDirectionApplicable = null;
}
@@ -119,18 +121,18 @@ namespace UniVRM10
{
// 1. Get eye direction from provider.
_inputEyeDirection = _eyeDirectionProvider?.EyeDirection ?? default;
// 2. Validate user input, and Output as actual weights.
_validator.Validate(_inputWeights, _actualWeights,
_inputEyeDirection, out _actualEyeDirection,
out var blink, out var lookAt, out var mouth);
// 3. Set eye direction expression weights or any other side-effects (ex. eye bone).
_eyeDirectionApplicable?.Apply(_actualEyeDirection, _actualWeights);
// 4. Set actual weights to raw blendshapes.
_merger.SetValues(_actualWeights);
BlinkOverrideRate = blink;
LookAtOverrideRate = lookAt;
MouthOverrideRate = mouth;

View File

@@ -92,7 +92,7 @@ namespace UniVRM10
{
switch (x.FirstPersonFlag)
{
case VrmLib.FirstPersonMeshType.Auto:
case UniGLTF.Extensions.VRMC_vrm.FirstPersonType.auto:
{
if (x.Renderer is SkinnedMeshRenderer smr)
{
@@ -131,17 +131,17 @@ namespace UniVRM10
}
break;
case VrmLib.FirstPersonMeshType.FirstPersonOnly:
case UniGLTF.Extensions.VRMC_vrm.FirstPersonType.firstPersonOnly:
// 1人称のカメラでだけ描画されるようにする
x.Renderer.gameObject.layer = FIRSTPERSON_ONLY_LAYER;
break;
case VrmLib.FirstPersonMeshType.ThirdPersonOnly:
case UniGLTF.Extensions.VRMC_vrm.FirstPersonType.thirdPersonOnly:
// 3人称のカメラでだけ描画されるようにする
x.Renderer.gameObject.layer = THIRDPERSON_ONLY_LAYER;
break;
case VrmLib.FirstPersonMeshType.Both:
case UniGLTF.Extensions.VRMC_vrm.FirstPersonType.both:
// 特に何もしない。すべてのカメラで描画される
break;
}

View File

@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using VrmLib;
using UniGLTF.Extensions.VRMC_vrm;
#if UNITY_EDITOR
using UnityEditor;
#endif
@@ -11,14 +10,6 @@ namespace UniVRM10
[Serializable]
public class VRM10ControllerLookAt : ILookAtEyeDirectionProvider
{
public enum LookAtTypes
{
// Gaze control by bone (leftEye, rightEye)
Bone,
// Gaze control by blend shape (lookUp, lookDown, lookLeft, lookRight)
Expression,
}
public enum LookAtTargetTypes
{
CalcYawPitchToGaze,
@@ -32,7 +23,7 @@ namespace UniVRM10
public Vector3 OffsetFromHead = new Vector3(0, 0.06f, 0);
[SerializeField]
public LookAtTypes LookAtType;
public LookAtType LookAtType;
[SerializeField]
public CurveMapper HorizontalOuter = new CurveMapper(90.0f, 10.0f);
@@ -55,7 +46,7 @@ namespace UniVRM10
private ILookAtEyeDirectionApplicable _eyeDirectionApplicable;
internal ILookAtEyeDirectionApplicable EyeDirectionApplicable => _eyeDirectionApplicable;
public LookAtEyeDirection EyeDirection { get; private set; }
#region LookAtTargetTypes.CalcYawPitchToGaze
@@ -150,10 +141,10 @@ namespace UniVRM10
}
switch (LookAtType)
{
case LookAtTypes.Bone:
case LookAtType.bone:
_eyeDirectionApplicable = new LookAtEyeDirectionApplicableToBone(m_leftEye, m_rightEye, HorizontalOuter, HorizontalInner, VerticalDown, VerticalUp);
break;
case LookAtTypes.Expression:
case LookAtType.expression:
_eyeDirectionApplicable = new LookAtEyeDirectionApplicableToExpression(HorizontalOuter, HorizontalInner, VerticalDown, VerticalUp);
break;
default:

View File

@@ -1,89 +0,0 @@
using System;
using VrmLib;
namespace UniVRM10
{
/// <summary>
/// for exporter
/// </summary>
public class ArrayByteBuffer10
{
public ArraySegment<byte> Bytes
{
get
{
if (m_bytes == null)
{
return new ArraySegment<byte>();
}
return new ArraySegment<byte>(m_bytes, 0, m_used);
}
}
Byte[] m_bytes;
int m_used = 0;
public ArrayByteBuffer10(Byte[] bytes = null)
{
m_bytes = bytes ?? (new byte[] { });
}
public ArrayByteBuffer10(Byte[] bytes, int used)
{
m_bytes = bytes ?? (new byte[] { });
m_used = used;
}
public void ExtendCapacity(int byteLength)
{
var backup = m_bytes;
m_bytes = new byte[backup.Length + byteLength];
backup.CopyTo(m_bytes, backup.Length);
}
public void Extend(ArraySegment<byte> array, int stride, out int offset, out int length)
{
var tmp = m_bytes;
// alignment
var padding = m_used % stride == 0 ? 0 : stride - m_used % stride;
if (m_bytes == null || m_used + padding + array.Count > m_bytes.Length)
{
// recreate buffer
var newSize = Math.Max(m_used + padding + array.Count, m_bytes.Length * 2);
m_bytes = new Byte[newSize];
if (m_used > 0)
{
Buffer.BlockCopy(tmp, 0, m_bytes, 0, m_used);
}
}
if (m_used + padding + array.Count > m_bytes.Length)
{
throw new ArgumentOutOfRangeException();
}
Buffer.BlockCopy(array.Array, array.Offset, m_bytes, m_used + padding, array.Count);
length = array.Count;
offset = m_used + padding;
// var result = new GltfBufferView
// {
// buffer = 0,
// byteLength = array.Length,
// byteOffset = m_used + padding,
// target = target,
// };
// if (target == GltfBufferTargetType.ARRAY_BUFFER)
// {
// result.byteStride = stride;
// }
m_used = m_used + padding + array.Count;
// return result;
}
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: c700d6d6fbb38fa4d9662213c58d5725
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,23 +1,9 @@
using System;
using System.Collections.Generic;
using System.Numerics;
using VrmLib;
namespace UniVRM10
{
public static class ArrayExtensions
{
public static Vector2 ToVector2(this float[] src, Vector2 defaultValue = default)
{
if (src.Length != 2) return defaultValue;
var v = new Vector2();
v.X = src[0];
v.Y = src[1];
return v;
}
public static Vector3 ToVector3(this float[] src, Vector3 defaultValue = default)
{
if (src.Length != 3) return defaultValue;
@@ -36,74 +22,5 @@ namespace UniVRM10
var v = new Quaternion(src[0], src[1], src[2], src[3]);
return v;
}
public static TextureInfo GetTexture(this int? nullable, List<Texture> textures)
{
if (!nullable.TryGetValidIndex(textures.Count, out int index))
{
return null;
}
var texture = textures[index];
return new TextureInfo(texture);
}
public static TextureInfo GetTexture(this int index, List<Texture> textures)
{
if (index < 0 || index >= textures.Count)
{
return null;
}
var texture = textures[index];
return new TextureInfo(texture);
}
public static int? ToIndex(this TextureInfo texture, List<Texture> textures)
{
if (texture == null)
{
return default;
}
return textures.IndexOfThrow(texture.Texture);
}
public static Vector4 ToVector4(this float[] src, Vector4 defaultValue = default)
{
switch (src.Length)
{
case 4:
return new Vector4(src[0], src[1], src[2], src[3]);
case 3:
return new Vector4(src[0], src[1], src[2], 1.0f);
case 0:
return defaultValue;
default:
throw new Exception();
}
}
public static LinearColor ToLinearColor(this float[] src, Vector4 defaultValue)
{
switch (src.Length)
{
case 4:
return LinearColor.FromLiner(src[0], src[1], src[2], src[3]);
case 3:
return LinearColor.FromLiner(src[0], src[1], src[2], 1.0f);
case 0:
return LinearColor.FromLiner(defaultValue);
default:
throw new Exception();
}
}
public static float[] ToFloat2(this System.Numerics.Vector2 value)
{
return new float[] { value.X, value.Y };
}
public static float[] ToFloat4(this System.Numerics.Vector4 value)
{
return new float[] { value.X, value.Y, value.Z, value.W };
}
}
}

View File

@@ -39,7 +39,7 @@ namespace UniVRM10
count = self.Count;
}
var slice = self.Bytes.Slice(offset * stride, count * stride);
return storage.AppendToBuffer(bufferIndex, slice, stride);
return storage.AppendToBuffer(bufferIndex, slice);
}
static glTFAccessor CreateGltfAccessor(this VrmLib.BufferAccessor self,
@@ -116,8 +116,8 @@ namespace UniVRM10
sparseValueSpan[i] = value;
}
var sparseIndexView = storage.AppendToBuffer(bufferIndex, sparseIndexBin, 4);
var sparseValueView = storage.AppendToBuffer(bufferIndex, sparseValueBin, 12);
var sparseIndexView = storage.AppendToBuffer(bufferIndex, sparseIndexBin);
var sparseValueView = storage.AppendToBuffer(bufferIndex, sparseValueBin);
var accessorIndex = storage.Gltf.accessors.Count;
var accessor = new glTFAccessor

View File

@@ -0,0 +1,29 @@
using System;
using UnityEngine;
using System.Linq;
using System.Collections.Generic;
namespace UniVRM10
{
public static class ComponentBuilder
{
#region Util
static (Transform, Mesh) GetTransformAndMesh(Transform t)
{
var skinnedMeshRenderer = t.GetComponent<SkinnedMeshRenderer>();
if (skinnedMeshRenderer != null)
{
return (t, skinnedMeshRenderer.sharedMesh);
}
var filter = t.GetComponent<MeshFilter>();
if (filter != null)
{
return (t, filter.sharedMesh);
}
return default;
}
#endregion
}
}

View File

@@ -0,0 +1,84 @@
using System;
using System.Collections.Generic;
using UniGLTF.Extensions.VRMC_vrm;
using UnityEngine;
namespace UniVRM10
{
public static class ExpressionExtensions
{
/// <summary>
/// for SubAssetName
/// </summary>
/// <returns></returns>
public static string ExtractName(this Expression expression)
{
ExpressionKey key =
(expression.Preset == ExpressionPreset.custom)
? ExpressionKey.CreateCustom(expression.Name)
: ExpressionKey.CreateFromPreset(expression.Preset)
;
return $"Expression.{key}";
}
public static UniVRM10.MorphTargetBinding Build10(this MorphTargetBind bind, GameObject root, RuntimeUnityBuilder.ModelMap loader, VrmLib.Model model)
{
var libNode = model.Nodes[bind.Node.Value];
var node = loader.Nodes[libNode].transform;
var mesh = loader.Meshes[libNode.MeshGroup];
var relativePath = node.RelativePathFrom(root.transform);
// VRM-1.0 では値域は [0-1.0f]
return new UniVRM10.MorphTargetBinding(relativePath, bind.Index.Value, bind.Weight.Value * 100.0f);
}
public static UniVRM10.MaterialColorBinding? Build10(this MaterialColorBind bind, IReadOnlyList<VRMShaders.MaterialFactory.MaterialLoadInfo> materials)
{
var value = new Vector4(bind.TargetValue[0], bind.TargetValue[1], bind.TargetValue[2], bind.TargetValue[3]);
var material = materials[bind.Material.Value].Asset;
var binding = default(UniVRM10.MaterialColorBinding?);
if (material != null)
{
try
{
binding = new UniVRM10.MaterialColorBinding
{
MaterialName = material.name, // 名前で持つべき?
BindType = bind.Type,
TargetValue = value,
// BaseValue = material.GetColor(kv.Key),
};
}
catch (Exception)
{
// do nothing
}
}
return binding;
}
public static UniVRM10.MaterialUVBinding? Build10(this TextureTransformBind bind, IReadOnlyList<VRMShaders.MaterialFactory.MaterialLoadInfo> materials)
{
var material = materials[bind.Material.Value].Asset;
var binding = default(UniVRM10.MaterialUVBinding?);
if (material != null)
{
try
{
binding = new UniVRM10.MaterialUVBinding
{
MaterialName = material.name, // 名前で持つべき
Scaling = new Vector2(bind.Scaling[0], bind.Scaling[1]),
Offset = new Vector2(bind.Offset[0], bind.Offset[1]),
};
}
catch (Exception)
{
// do nothing
}
}
return binding;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c93dae149b843ca46b028b4e4d845c89
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,100 +0,0 @@
using System;
using UniGLTF;
namespace UniVRM10
{
public static class ImageAdapter
{
public static VrmLib.Image FromGltf(this glTFImage x, Vrm10Storage storage)
{
if (x.bufferView == -1)
{
// 外部参照?
throw new Exception();
}
var view = storage.Gltf.bufferViews[x.bufferView];
var buffer = storage.Gltf.buffers[view.buffer];
// テクスチャの用途を調べる
var usage = default(VrmLib.ImageUsage);
foreach (var material in storage.Gltf.materials)
{
var colorImage = GetColorImage(storage, material);
if (colorImage == x)
{
usage |= VrmLib.ImageUsage.Color;
}
var normalImage = GetNormalImage(storage, material);
if (normalImage == x)
{
usage |= VrmLib.ImageUsage.Normal;
}
}
var memory = storage.GetBufferBytes(buffer);
return new VrmLib.Image(x.name,
x.mimeType,
usage,
memory.Slice(view.byteOffset, view.byteLength));
}
static glTFImage GetTexture(Vrm10Storage storage, int index)
{
if (index < 0 || index >= storage.Gltf.textures.Count)
{
return null;
}
var texture = storage.Gltf.textures[index];
if (texture.source < 0 || texture.source >= storage.Gltf.images.Count)
{
return null;
}
return storage.Gltf.images[texture.source];
}
static glTFImage GetColorImage(Vrm10Storage storage, glTFMaterial m)
{
if (m.pbrMetallicRoughness == null)
{
return null;
}
if (m.pbrMetallicRoughness.baseColorTexture == null)
{
return null;
}
if (!m.pbrMetallicRoughness.baseColorTexture.index.TryGetValidIndex(storage.TextureCount, out int index))
{
return null;
}
return GetTexture(storage, index);
}
static glTFImage GetNormalImage(Vrm10Storage storage, glTFMaterial m)
{
if (m.normalTexture == null)
{
return null;
}
if (!m.normalTexture.index.TryGetValidIndex(storage.TextureCount, out int index))
{
return null;
}
return GetTexture(storage, index);
}
public static glTFImage ToGltf(this VrmLib.Image src, Vrm10Storage storage)
{
var viewIndex = storage.AppendToBuffer(0, src.Bytes, 1);
var gltf = storage.Gltf;
return new glTFImage
{
name = src.Name,
mimeType = src.MimeType,
bufferView = viewIndex,
};
}
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: d48a6bb715d0d024fa5af64bb63f695e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,263 +0,0 @@
using System;
using System.Collections.Generic;
using System.Numerics;
using VrmLib.MToon;
using VrmLib;
using UniGLTF;
using UniGLTF.Extensions.VRMC_materials_mtoon;
using UniJSON;
namespace UniVRM10
{
public static class MToonAdapter
{
// for debug
static readonly Vector4 Nan = new Vector4(float.NaN, float.NaN, float.NaN, float.NaN);
static RenderMode GetRenderMode(string alphaMode, bool isTransparentWithZWrite)
{
switch (alphaMode)
{
case "OPAQUE": return RenderMode.Opaque;
case "MASK": return RenderMode.Cutout;
case "BLEND":
{
if (isTransparentWithZWrite)
{
return RenderMode.TransparentWithZWrite;
}
else
{
return RenderMode.Transparent;
}
}
}
throw new NotImplementedException();
}
public static MToonMaterial MToonFromGltf(glTFMaterial material, List<Texture> textures, VRMC_materials_mtoon extension)
{
var mtoon = new MToonMaterial(material.name);
var Meta = new MetaDefinition
{
Implementation = "Santarh/MToon",
};
var Color = new ColorDefinition
{
LitColor = material.pbrMetallicRoughness.baseColorFactor.ToLinearColor(Nan),
LitMultiplyTexture = material.pbrMetallicRoughness.baseColorTexture?.index.GetTexture(textures),
ShadeColor = extension.ShadeFactor.ToLinearColor(Nan),
ShadeMultiplyTexture = extension.ShadeMultiplyTexture.GetTexture(textures),
CutoutThresholdValue = material.alphaCutoff,
};
var Outline = new OutlineDefinition
{
OutlineColorMode = (VrmLib.MToon.OutlineColorMode)extension.OutlineColorMode,
OutlineColor = extension.OutlineFactor.ToLinearColor(Nan),
OutlineLightingMixValue = extension.OutlineLightingMixFactor.Value,
OutlineScaledMaxDistanceValue = extension.OutlineScaledMaxDistanceFactor.Value,
OutlineWidthMode = (VrmLib.MToon.OutlineWidthMode)extension.OutlineWidthMode,
OutlineWidthValue = extension.OutlineWidthFactor.Value,
OutlineWidthMultiplyTexture = extension.OutlineWidthMultiplyTexture.GetTexture(textures),
};
var Emission = new EmissionDefinition
{
EmissionColor = material.emissiveFactor.ToLinearColor(Nan),
};
if (material.emissiveTexture != null)
{
Emission.EmissionMultiplyTexture = material.emissiveTexture.index.GetTexture(textures);
}
var Lighting = new LightingDefinition
{
LightingInfluence = new LightingInfluenceDefinition
{
GiIntensityValue = extension.GiIntensityFactor.Value,
LightColorAttenuationValue = extension.LightColorAttenuationFactor.Value,
},
LitAndShadeMixing = new LitAndShadeMixingDefinition
{
ShadingShiftValue = extension.ShadingShiftFactor.Value,
ShadingToonyValue = extension.ShadingToonyFactor.Value,
},
Normal = new NormalDefinition
{
},
};
if (material.normalTexture != null)
{
Lighting.Normal.NormalScaleValue = material.normalTexture.scale;
Lighting.Normal.NormalTexture = material.normalTexture.index.GetTexture(textures);
}
var MatCap = new MatCapDefinition
{
AdditiveTexture = extension.AdditiveTexture.GetTexture(textures)
};
var Rendering = new RenderingDefinition
{
CullMode = material.doubleSided ? CullMode.Off : CullMode.Back,
RenderMode = GetRenderMode(material.alphaMode, extension.TransparentWithZWrite.Value),
RenderQueueOffsetNumber = extension.RenderQueueOffsetNumber.Value,
};
var Rim = new RimDefinition
{
RimColor = extension.RimFactor.ToLinearColor(Nan),
RimMultiplyTexture = extension.RimMultiplyTexture.GetTexture(textures),
RimLiftValue = extension.RimLiftFactor.Value,
RimFresnelPowerValue = extension.RimFresnelPowerFactor.Value,
RimLightingMixValue = extension.RimLightingMixFactor.Value,
};
var TextureOption = new TextureUvCoordsDefinition
{
UvAnimationMaskTexture = extension.UvAnimationMaskTexture.GetTexture(textures),
UvAnimationRotationSpeedValue = extension.UvAnimationRotationSpeedFactor.Value,
UvAnimationScrollXSpeedValue = extension.UvAnimationScrollXSpeedFactor.Value,
UvAnimationScrollYSpeedValue = extension.UvAnimationScrollYSpeedFactor.Value,
};
if (glTF_KHR_texture_transform.TryGet(material.pbrMetallicRoughness.baseColorTexture, out glTF_KHR_texture_transform t))
{
TextureOption.MainTextureLeftBottomOriginOffset = t.offset.ToVector2();
TextureOption.MainTextureLeftBottomOriginScale = t.scale.ToVector2();
}
mtoon.Definition = new MToonDefinition
{
Meta = Meta,
Color = Color,
Outline = Outline,
Emission = Emission,
Lighting = Lighting,
MatCap = MatCap,
Rendering = Rendering,
Rim = Rim,
TextureOption = TextureOption,
};
return mtoon;
}
static (string, bool) GetRenderMode(RenderMode mode)
{
switch (mode)
{
case RenderMode.Opaque: return ("OPAQUE", false);
case RenderMode.Cutout: return ("MASK", false);
case RenderMode.Transparent: return ("BLEND", false);
case RenderMode.TransparentWithZWrite: return ("BLEND", true);
}
throw new NotImplementedException();
}
public static glTFMaterial MToonToGltf(this MToonMaterial mtoon, List<Texture> textures)
{
var material = mtoon.UnlitToGltf(textures);
var dst = new VRMC_materials_mtoon();
// Color
material.pbrMetallicRoughness.baseColorFactor = mtoon.Definition.Color.LitColor.ToFloat4();
if (mtoon.Definition.Color.LitMultiplyTexture != null)
{
material.pbrMetallicRoughness.baseColorTexture = new glTFMaterialBaseColorTextureInfo
{
index = mtoon.Definition.Color.LitMultiplyTexture.ToIndex(textures).Value
};
}
dst.ShadeFactor = mtoon.Definition.Color.ShadeColor.ToFloat3();
dst.ShadeMultiplyTexture = mtoon.Definition.Color.ShadeMultiplyTexture.ToIndex(textures);
material.alphaCutoff = mtoon.Definition.Color.CutoutThresholdValue;
// Outline
dst.OutlineColorMode = (UniGLTF.Extensions.VRMC_materials_mtoon.OutlineColorMode)mtoon.Definition.Outline.OutlineColorMode;
dst.OutlineFactor = mtoon.Definition.Outline.OutlineColor.ToFloat3();
dst.OutlineLightingMixFactor = mtoon.Definition.Outline.OutlineLightingMixValue;
dst.OutlineScaledMaxDistanceFactor = mtoon.Definition.Outline.OutlineScaledMaxDistanceValue;
dst.OutlineWidthMode = (UniGLTF.Extensions.VRMC_materials_mtoon.OutlineWidthMode)mtoon.Definition.Outline.OutlineWidthMode;
dst.OutlineWidthFactor = mtoon.Definition.Outline.OutlineWidthValue;
dst.OutlineWidthMultiplyTexture = mtoon.Definition.Outline.OutlineWidthMultiplyTexture.ToIndex(textures);
// Emission
material.emissiveFactor = mtoon.Definition.Emission.EmissionColor.ToFloat3();
if (mtoon.Definition.Emission.EmissionMultiplyTexture != null)
{
material.emissiveTexture = new glTFMaterialEmissiveTextureInfo
{
index = textures.IndexOfNullable(mtoon.Definition.Emission.EmissionMultiplyTexture.Texture).Value
};
}
// Light
dst.GiIntensityFactor = mtoon.Definition.Lighting.LightingInfluence.GiIntensityValue;
dst.LightColorAttenuationFactor = mtoon.Definition.Lighting.LightingInfluence.LightColorAttenuationValue;
dst.ShadingShiftFactor = mtoon.Definition.Lighting.LitAndShadeMixing.ShadingShiftValue;
dst.ShadingToonyFactor = mtoon.Definition.Lighting.LitAndShadeMixing.ShadingToonyValue;
if (mtoon.Definition.Lighting.Normal.NormalTexture != null)
{
material.normalTexture = new glTFMaterialNormalTextureInfo
{
index = textures.IndexOfNullable(mtoon.Definition.Lighting.Normal.NormalTexture.Texture).Value,
scale = mtoon.Definition.Lighting.Normal.NormalScaleValue
};
}
// matcap
dst.AdditiveTexture = mtoon.Definition.MatCap.AdditiveTexture.ToIndex(textures);
// rendering
switch (mtoon.Definition.Rendering.CullMode)
{
case CullMode.Back:
material.doubleSided = false;
break;
case CullMode.Off:
material.doubleSided = true;
break;
case CullMode.Front:
// GLTF not support
material.doubleSided = false;
break;
default:
throw new NotImplementedException();
}
(material.alphaMode, dst.TransparentWithZWrite) = GetRenderMode(mtoon.Definition.Rendering.RenderMode);
dst.RenderQueueOffsetNumber = mtoon.Definition.Rendering.RenderQueueOffsetNumber;
// rim
dst.RimFactor = mtoon.Definition.Rim.RimColor.ToFloat3();
dst.RimMultiplyTexture = mtoon.Definition.Rim.RimMultiplyTexture.ToIndex(textures);
dst.RimLiftFactor = mtoon.Definition.Rim.RimLiftValue;
dst.RimFresnelPowerFactor = mtoon.Definition.Rim.RimFresnelPowerValue;
dst.RimLightingMixFactor = mtoon.Definition.Rim.RimLightingMixValue;
// texture option
dst.UvAnimationMaskTexture = mtoon.Definition.TextureOption.UvAnimationMaskTexture.ToIndex(textures);
dst.UvAnimationRotationSpeedFactor = mtoon.Definition.TextureOption.UvAnimationRotationSpeedValue;
dst.UvAnimationScrollXSpeedFactor = mtoon.Definition.TextureOption.UvAnimationScrollXSpeedValue;
dst.UvAnimationScrollYSpeedFactor = mtoon.Definition.TextureOption.UvAnimationScrollYSpeedValue;
if (material.pbrMetallicRoughness.baseColorTexture != null)
{
var offset = mtoon.Definition.TextureOption.MainTextureLeftBottomOriginOffset;
var scale = mtoon.Definition.TextureOption.MainTextureLeftBottomOriginScale;
glTF_KHR_texture_transform.Serialize(
material.pbrMetallicRoughness.baseColorTexture,
(offset.X, offset.Y),
(scale.X, scale.Y)
);
}
UniGLTF.Extensions.VRMC_materials_mtoon.GltfSerializer.SerializeTo(ref material.extensions, dst);
return material;
}
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: dfbed4ddbad0e1941862133ed8219c4c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,312 +0,0 @@
using Color = System.Numerics.Vector4;
using Material = UniGLTF.glTFMaterial;
using System.Collections.Generic;
using VrmLib;
using VrmLib.MToon;
using System;
namespace UniVRM10
{
public static partial class Utils
{
public static void ToProtobuf(this LinearColor color, Action<float> add, bool hasAlpha)
{
add(color.RGBA.X);
add(color.RGBA.Y);
add(color.RGBA.Z);
if (hasAlpha)
{
add(color.RGBA.W);
}
}
// public static void SetMToonParametersToMaterial(Material material, MToonDefinition parameters, List<Texture> textures)
// {
// var mtoon = material.Extensions.VRMCMaterialsMtoon;
// {
// var meta = parameters.Meta;
// mtoon.Version = meta.VersionNumber.ToString();
// }
// // TODO:
// // {
// // var rendering = parameters.Rendering;
// // ValidateBlendMode(material, rendering.RenderMode, isChangedByUser: true);
// // ValidateCullMode(material, rendering.CullMode);
// // ValidateRenderQueue(material, offset: rendering.RenderQueueOffsetNumber);
// // }
// {
// var color = parameters.Color;
// // SetColor(material, MToonUtils.PropColor, color.LitColor);
// color.LitColor.ToProtobuf(mtoon.LitFactor.Add, true);
// // SetTexture(material, MToonUtils.PropMainTex, color.LitMultiplyTexture, textures);
// mtoon.LitMultiplyTexture = textures.IndexOfNullable(color.LitMultiplyTexture.Texture);
// // SetColor(material, MToonUtils.PropShadeColor, color.ShadeColor);
// color.ShadeColor.ToProtobuf(mtoon.ShadeFactor.Add, false);
// // SetTexture(material, MToonUtils.PropShadeTexture, color.ShadeMultiplyTexture, textures);
// mtoon.ShadeMultiplyTexture = textures.IndexOfNullable(color.ShadeMultiplyTexture.Texture);
// // SetValue(material, MToonUtils.PropCutoff, color.CutoutThresholdValue);
// mtoon.CutoutThresholdFactor = color.CutoutThresholdValue;
// }
// {
// var lighting = parameters.Lighting;
// {
// var prop = lighting.LitAndShadeMixing;
// // SetValue(material, MToonUtils.PropShadeShift, prop.ShadingShiftValue);
// mtoon.ShadingShiftFactor = prop.ShadingShiftValue;
// // SetValue(material, MToonUtils.PropShadeToony, prop.ShadingToonyValue);
// mtoon.ShadingToonyFactor = prop.ShadingToonyValue;
// }
// {
// var prop = lighting.LightingInfluence;
// // SetValue(material, MToonUtils.PropLightColorAttenuation, prop.LightColorAttenuationValue);
// mtoon.LightColorAttenuationFactor = prop.LightColorAttenuationValue;
// // SetValue(material, MToonUtils.PropIndirectLightIntensity, prop.GiIntensityValue);
// mtoon.GiIntensityFactor = prop.GiIntensityValue;
// }
// {
// var prop = lighting.Normal;
// // SetTexture(material, MToonUtils.PropBumpMap, prop.NormalTexture, textures);
// mtoon.NormalTexture = textures.IndexOfNullable(prop.NormalTexture.Texture);
// // SetValue(material, MToonUtils.PropBumpScale, prop.NormalScaleValue);
// mtoon.NormalScaleFactor = prop.NormalScaleValue;
// }
// }
// {
// var emission = parameters.Emission;
// // SetColor(material, MToonUtils.PropEmissionColor, emission.EmissionColor);
// emission.EmissionColor.ToProtobuf(mtoon.EmissionFactor.Add, false);
// // SetTexture(material, MToonUtils.PropEmissionMap, emission.EmissionMultiplyTexture, textures);
// mtoon.EmissionMultiplyTexture = textures.IndexOfNullable(emission.EmissionMultiplyTexture.Texture);
// }
// {
// var matcap = parameters.MatCap;
// // SetTexture(material, MToonUtils.PropSphereAdd, matcap.AdditiveTexture, textures);
// mtoon.AdditiveTexture = textures.IndexOfNullable(matcap.AdditiveTexture.Texture);
// }
// {
// var rim = parameters.Rim;
// // SetColor(material, MToonUtils.PropRimColor, rim.RimColor);
// rim.RimColor.ToProtobuf(mtoon.RimFactor.Add, false);
// // SetTexture(material, MToonUtils.PropRimTexture, rim.RimMultiplyTexture, textures);
// mtoon.RimMultiplyTexture = textures.IndexOfNullable(rim.RimMultiplyTexture.Texture);
// // SetValue(material, MToonUtils.PropRimLightingMix, rim.RimLightingMixValue);
// mtoon.RimLightingMixFactor = rim.RimLightingMixValue;
// // SetValue(material, MToonUtils.PropRimFresnelPower, rim.RimFresnelPowerValue);
// mtoon.RimFresnelPowerFactor = rim.RimFresnelPowerValue;
// // SetValue(material, MToonUtils.PropRimLift, rim.RimLiftValue);
// mtoon.RimLiftFactor = rim.RimLiftValue;
// }
// {
// var outline = parameters.Outline;
// // SetValue(material, MToonUtils.PropOutlineWidth, outline.OutlineWidthValue);
// mtoon.OutlineWidthFactor = outline.OutlineWidthValue;
// // SetTexture(material, MToonUtils.PropOutlineWidthTexture, outline.OutlineWidthMultiplyTexture, textures);
// mtoon.OutlineWidthMultiplyTexture = textures.IndexOfNullable(outline.OutlineWidthMultiplyTexture.Texture);
// // SetValue(material, MToonUtils.PropOutlineScaledMaxDistance, outline.OutlineScaledMaxDistanceValue);
// mtoon.OutlineScaledMaxDistanceFactor = outline.OutlineScaledMaxDistanceValue;
// // SetColor(material, MToonUtils.PropOutlineColor, outline.OutlineColor);
// outline.OutlineColor.ToProtobuf(mtoon.OutlineFactor.Add, false);
// // SetValue(material, MToonUtils.PropOutlineLightingMix, outline.OutlineLightingMixValue);
// mtoon.OutlineLightingMixFactor = outline.OutlineLightingMixValue;
// // ValidateOutlineMode(material, outline.OutlineWidthMode, outline.OutlineColorMode);
// }
// {
// var textureOptions = parameters.TextureOption;
// // TODO:
// // material.SetTextureScale(MToonUtils.PropMainTex, textureOptions.MainTextureLeftBottomOriginScale);
// // material.SetTextureOffset(MToonUtils.PropMainTex, textureOptions.MainTextureLeftBottomOriginOffset);
// // material.SetTexture(MToonUtils.PropUvAnimMaskTexture, textureOptions.UvAnimationMaskTexture, textures);
// mtoon.UvAnimationMaskTexture = textures.IndexOfNullable(textureOptions.UvAnimationMaskTexture.Texture);
// // material.SetFloat(MToonUtils.PropUvAnimScrollX, textureOptions.UvAnimationScrollXSpeedValue);
// mtoon.UvAnimationScrollXSpeedFactor = textureOptions.UvAnimationScrollXSpeedValue;
// // material.SetFloat(MToonUtils.PropUvAnimScrollY, textureOptions.UvAnimationScrollYSpeedValue);
// mtoon.UvAnimationScrollYSpeedFactor = textureOptions.UvAnimationScrollYSpeedValue;
// // material.SetFloat(MToonUtils.PropUvAnimRotation, textureOptions.UvAnimationRotationSpeedValue);
// mtoon.UvAnimationRotationSpeedFactor = textureOptions.UvAnimationRotationSpeedValue;
// }
// }
// /// <summary>
// /// Validate properties and Set hidden properties, keywords.
// /// if isBlendModeChangedByUser is true, renderQueue will set specified render mode's default value.
// /// </summary>
// /// <param name="material"></param>
// /// <param name="isBlendModeChangedByUser"></param>
// public static void ValidateProperties(Material material, List<Texture> textures, bool isBlendModeChangedByUser = false)
// {
// ValidateBlendMode(material, (RenderMode)material.GetFloat(MToonUtils.PropBlendMode), isBlendModeChangedByUser);
// ValidateNormalMode(material, material.GetTexture(MToonUtils.PropBumpMap, textures) != null);
// ValidateOutlineMode(material,
// (OutlineWidthMode)material.GetFloat(MToonUtils.PropOutlineWidthMode),
// (OutlineColorMode)material.GetFloat(MToonUtils.PropOutlineColorMode));
// ValidateDebugMode(material, (DebugMode)material.GetFloat(MToonUtils.PropDebugMode));
// ValidateCullMode(material, (CullMode)material.GetFloat(MToonUtils.PropCullMode));
// var mainTex = material.GetTexture(MToonUtils.PropMainTex, textures);
// var shadeTex = material.GetTexture(MToonUtils.PropShadeTexture, textures);
// if (mainTex != null && shadeTex == null)
// {
// material.SetTexture(MToonUtils.PropShadeTexture, mainTex, textures);
// }
// }
// private static void ValidateDebugMode(Material material, DebugMode debugMode)
// {
// switch (debugMode)
// {
// case DebugMode.None:
// SetKeyword(material, MToonUtils.KeyDebugNormal, false);
// SetKeyword(material, MToonUtils.KeyDebugLitShadeRate, false);
// break;
// case DebugMode.Normal:
// SetKeyword(material, MToonUtils.KeyDebugNormal, true);
// SetKeyword(material, MToonUtils.KeyDebugLitShadeRate, false);
// break;
// case DebugMode.LitShadeRate:
// SetKeyword(material, MToonUtils.KeyDebugNormal, false);
// SetKeyword(material, MToonUtils.KeyDebugLitShadeRate, true);
// break;
// }
// }
// public static void ValidateBlendMode(Material material, RenderMode renderMode, bool isChangedByUser)
// {
// switch (renderMode)
// {
// case RenderMode.Opaque:
// material.SetOverrideTag(MToonUtils.TagRenderTypeKey, MToonUtils.TagRenderTypeValueOpaque);
// material.SetInt(MToonUtils.PropSrcBlend, BlendMode.One);
// material.SetInt(MToonUtils.PropDstBlend, BlendMode.Zero);
// material.SetInt(MToonUtils.PropZWrite, MToonUtils.EnabledIntValue);
// material.SetInt(MToonUtils.PropAlphaToMask, MToonUtils.DisabledIntValue);
// SetKeyword(material, MToonUtils.KeyAlphaTestOn, false);
// SetKeyword(material, MToonUtils.KeyAlphaBlendOn, false);
// SetKeyword(material, MToonUtils.KeyAlphaPremultiplyOn, false);
// break;
// case RenderMode.Cutout:
// material.SetOverrideTag(MToonUtils.TagRenderTypeKey, MToonUtils.TagRenderTypeValueTransparentCutout);
// material.SetInt(MToonUtils.PropSrcBlend, BlendMode.One);
// material.SetInt(MToonUtils.PropDstBlend, BlendMode.Zero);
// material.SetInt(MToonUtils.PropZWrite, MToonUtils.EnabledIntValue);
// material.SetInt(MToonUtils.PropAlphaToMask, MToonUtils.EnabledIntValue);
// SetKeyword(material, MToonUtils.KeyAlphaTestOn, true);
// SetKeyword(material, MToonUtils.KeyAlphaBlendOn, false);
// SetKeyword(material, MToonUtils.KeyAlphaPremultiplyOn, false);
// break;
// case RenderMode.Transparent:
// material.SetOverrideTag(MToonUtils.TagRenderTypeKey, MToonUtils.TagRenderTypeValueTransparent);
// material.SetInt(MToonUtils.PropSrcBlend, BlendMode.SrcAlpha);
// material.SetInt(MToonUtils.PropDstBlend, BlendMode.OneMinusSrcAlpha);
// material.SetInt(MToonUtils.PropZWrite, MToonUtils.DisabledIntValue);
// material.SetInt(MToonUtils.PropAlphaToMask, MToonUtils.DisabledIntValue);
// SetKeyword(material, MToonUtils.KeyAlphaTestOn, false);
// SetKeyword(material, MToonUtils.KeyAlphaBlendOn, true);
// SetKeyword(material, MToonUtils.KeyAlphaPremultiplyOn, false);
// break;
// case RenderMode.TransparentWithZWrite:
// material.SetOverrideTag(MToonUtils.TagRenderTypeKey, MToonUtils.TagRenderTypeValueTransparent);
// material.SetInt(MToonUtils.PropSrcBlend, BlendMode.SrcAlpha);
// material.SetInt(MToonUtils.PropDstBlend, BlendMode.OneMinusSrcAlpha);
// material.SetInt(MToonUtils.PropZWrite, MToonUtils.EnabledIntValue);
// material.SetInt(MToonUtils.PropAlphaToMask, MToonUtils.DisabledIntValue);
// SetKeyword(material, MToonUtils.KeyAlphaTestOn, false);
// SetKeyword(material, MToonUtils.KeyAlphaBlendOn, true);
// SetKeyword(material, MToonUtils.KeyAlphaPremultiplyOn, false);
// break;
// }
// if (isChangedByUser)
// {
// // ValidateRenderQueue(material, offset: 0);
// }
// else
// {
// var requirement = MToonUtils.GetRenderQueueRequirement(renderMode);
// // ValidateRenderQueue(material, offset: material.renderQueue - requirement.DefaultValue);
// }
// }
// private static void ValidateRenderQueue(Material material, int offset)
// {
// var requirement = MToonUtils.GetRenderQueueRequirement(GetBlendMode(material));
// var value = Mathf.Clamp(requirement.DefaultValue + offset, requirement.MinValue, requirement.MaxValue);
// material.renderQueue = value;
// }
// private static void ValidateOutlineMode(Material material, OutlineWidthMode outlineWidthMode,
// OutlineColorMode outlineColorMode)
// {
// var isFixed = outlineColorMode == OutlineColorMode.FixedColor;
// var isMixed = outlineColorMode == OutlineColorMode.MixedLighting;
// switch (outlineWidthMode)
// {
// case OutlineWidthMode.None:
// SetKeyword(material, MToonUtils.KeyOutlineWidthWorld, false);
// SetKeyword(material, MToonUtils.KeyOutlineWidthScreen, false);
// SetKeyword(material, MToonUtils.KeyOutlineColorFixed, false);
// SetKeyword(material, MToonUtils.KeyOutlineColorMixed, false);
// break;
// case OutlineWidthMode.WorldCoordinates:
// SetKeyword(material, MToonUtils.KeyOutlineWidthWorld, true);
// SetKeyword(material, MToonUtils.KeyOutlineWidthScreen, false);
// SetKeyword(material, MToonUtils.KeyOutlineColorFixed, isFixed);
// SetKeyword(material, MToonUtils.KeyOutlineColorMixed, isMixed);
// break;
// case OutlineWidthMode.ScreenCoordinates:
// SetKeyword(material, MToonUtils.KeyOutlineWidthWorld, false);
// SetKeyword(material, MToonUtils.KeyOutlineWidthScreen, true);
// SetKeyword(material, MToonUtils.KeyOutlineColorFixed, isFixed);
// SetKeyword(material, MToonUtils.KeyOutlineColorMixed, isMixed);
// break;
// }
// }
// private static void ValidateNormalMode(Material material, bool requireNormalMapping)
// {
// SetKeyword(material, MToonUtils.KeyNormalMap, requireNormalMapping);
// }
// private static void ValidateCullMode(Material material, CullMode cullMode)
// {
// switch (cullMode)
// {
// case CullMode.Back:
// material.SetInt(MToonUtils.PropCullMode, CullMode.Back);
// material.SetInt(MToonUtils.PropOutlineCullMode, CullMode.Front);
// break;
// case CullMode.Front:
// material.SetInt(MToonUtils.PropCullMode, CullMode.Front);
// material.SetInt(MToonUtils.PropOutlineCullMode, CullMode.Back);
// break;
// case CullMode.Off:
// material.SetInt(MToonUtils.PropCullMode, CullMode.Off);
// material.SetInt(MToonUtils.PropOutlineCullMode, CullMode.Front);
// break;
// }
// }
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 269eb140bd3b26043a6afac332268766
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,230 +0,0 @@
using VrmLib;
using System.Collections.Generic;
using System.Numerics;
using UniJSON;
using UniGLTF;
using System;
namespace UniVRM10
{
public static class MaterialAdapter
{
public static Material FromGltf(this glTFMaterial x, List<Texture> textures)
{
if (UniGLTF.Extensions.VRMC_materials_mtoon.GltfDeserializer.TryGet(x.extensions,
out UniGLTF.Extensions.VRMC_materials_mtoon.VRMC_materials_mtoon mtoon))
{
// mtoon
return MToonAdapter.MToonFromGltf(x, textures, mtoon);
}
if (glTF_KHR_materials_unlit.IsEnable(x))
{
// unlit
return UnlitFromGltf(x, textures);
}
// PBR
return PBRFromGltf(x, textures);
}
public static void LoadCommonParams(this Material self, glTFMaterial material, List<Texture> textures)
{
var pbr = material.pbrMetallicRoughness;
if (pbr.baseColorFactor != null)
{
self.BaseColorFactor = LinearColor.FromLiner(pbr.baseColorFactor);
}
var baseColorTexture = pbr.baseColorTexture;
if (baseColorTexture != null && baseColorTexture.index.TryGetValidIndex(textures.Count, out int index))
{
self.BaseColorTexture = new TextureInfo(textures[index]);
}
self.AlphaMode = EnumUtil.Parse<VrmLib.AlphaModeType>(material.alphaMode);
self.AlphaCutoff = material.alphaCutoff;
self.DoubleSided = material.doubleSided;
}
public static PBRMaterial PBRFromGltf(glTFMaterial material, List<Texture> textures)
{
var self = new PBRMaterial(material.name);
self.LoadCommonParams(material, textures);
//
// pbr
//
var pbr = material.pbrMetallicRoughness;
// metallic roughness
self.MetallicFactor = pbr.metallicFactor;
self.RoughnessFactor = pbr.roughnessFactor;
var metallicRoughnessTexture = pbr.metallicRoughnessTexture;
if (metallicRoughnessTexture != null
&& metallicRoughnessTexture.index.TryGetValidIndex(textures.Count, out int metallicRoughnessTextureIndex))
{
self.MetallicRoughnessTexture = textures[metallicRoughnessTextureIndex];
}
//
// emissive
//
if (material.emissiveFactor != null)
{
self.EmissiveFactor = new Vector3(
material.emissiveFactor[0],
material.emissiveFactor[1],
material.emissiveFactor[2]);
}
var emissiveTexture = material.emissiveTexture;
if (emissiveTexture != null
&& emissiveTexture.index.TryGetValidIndex(textures.Count, out int emissiveTextureIndex))
{
self.EmissiveTexture = textures[emissiveTextureIndex];
}
//
// normal
//
var normalTexture = material.normalTexture;
if (normalTexture != null
&& normalTexture.index.TryGetValidIndex(textures.Count, out int normalTextureIndex))
{
self.NormalTexture = textures[normalTextureIndex];
}
//
// occlusion
//
var occlusionTexture = material.occlusionTexture;
if (occlusionTexture != null
&& occlusionTexture.index.TryGetValidIndex(textures.Count, out int occlusionTextureIndex))
{
self.OcclusionTexture = textures[occlusionTextureIndex];
}
return self;
}
public static UnlitMaterial UnlitFromGltf(glTFMaterial material, List<Texture> textures)
{
var unlit = new UnlitMaterial(material.name);
unlit.LoadCommonParams(material, textures);
return unlit;
}
static string CastAlphaMode(VrmLib.AlphaModeType alphaMode)
{
if (alphaMode == AlphaModeType.BLEND_ZWRITE)
{
return "BLEND";
}
return alphaMode.ToString();
}
static glTFMaterial ToGltf(this VrmLib.Material src, List<Texture> textures)
{
var material = new glTFMaterial
{
name = src.Name,
pbrMetallicRoughness = new glTFPbrMetallicRoughness
{
baseColorFactor = src.BaseColorFactor.ToFloat4(),
},
alphaMode = CastAlphaMode(src.AlphaMode),
alphaCutoff = src.AlphaCutoff,
doubleSided = src.DoubleSided,
};
if (src.BaseColorTexture != null)
{
material.pbrMetallicRoughness.baseColorTexture = new glTFMaterialBaseColorTextureInfo
{
index = textures.IndexOfNullable(src.BaseColorTexture.Texture).Value,
};
}
return material;
}
public static glTFMaterial PBRToGltf(this PBRMaterial pbr, List<Texture> textures)
{
var material = pbr.ToGltf(textures);
// MetallicRoughness
material.pbrMetallicRoughness.baseColorFactor = pbr.BaseColorFactor.ToFloat4();
if (pbr.BaseColorTexture != null)
{
material.pbrMetallicRoughness.baseColorTexture = new glTFMaterialBaseColorTextureInfo
{
index = textures.IndexOfNullable(pbr.BaseColorTexture.Texture).Value,
};
}
material.pbrMetallicRoughness.metallicFactor = pbr.MetallicFactor;
material.pbrMetallicRoughness.roughnessFactor = pbr.RoughnessFactor;
if (pbr.MetallicRoughnessTexture != null)
{
material.pbrMetallicRoughness.metallicRoughnessTexture = new glTFMaterialMetallicRoughnessTextureInfo
{
index = textures.IndexOfNullable(pbr.MetallicRoughnessTexture).Value,
};
}
// Normal
if (pbr.NormalTexture != null)
{
material.normalTexture = new glTFMaterialNormalTextureInfo
{
index = textures.IndexOfNullable(pbr.NormalTexture).Value,
scale = pbr.NormalTextureScale
};
}
// Occlusion
if (pbr.OcclusionTexture != null)
{
material.occlusionTexture = new glTFMaterialOcclusionTextureInfo
{
index = textures.IndexOfNullable(pbr.OcclusionTexture).Value,
strength = pbr.OcclusionTextureStrength,
};
}
// Emissive
if (pbr.EmissiveTexture != null)
{
material.emissiveTexture = new glTFMaterialEmissiveTextureInfo
{
index = textures.IndexOfNullable(pbr.EmissiveTexture).Value,
};
}
material.emissiveFactor = pbr.EmissiveFactor.ToFloat3();
// AlphaMode
material.alphaMode = CastAlphaMode(pbr.AlphaMode);
// AlphaCutoff
material.alphaCutoff = pbr.AlphaCutoff;
// DoubleSided
material.doubleSided = pbr.DoubleSided;
return material;
}
public static glTFMaterial UnlitToGltf(this UnlitMaterial unlit, List<Texture> textures)
{
var material = unlit.ToGltf(textures);
if (!(material.extensions is glTFExtensionExport extensions))
{
extensions = new glTFExtensionExport();
material.extensions = extensions;
}
extensions.Add(
glTF_KHR_materials_unlit.ExtensionName,
new ArraySegment<byte>(glTF_KHR_materials_unlit.Raw));
material.pbrMetallicRoughness.roughnessFactor = 0.9f;
material.pbrMetallicRoughness.metallicFactor = 0.0f;
return material;
}
}
}

Some files were not shown because too many files have changed in this diff Show More