UniVRM/Scripts/Format/glTF_VRM_Material.cs
2018-07-31 22:04:01 +09:00

202 lines
7.6 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using UniGLTF;
using UnityEngine;
using UniJSON;
namespace VRM
{
[Serializable]
public class glTF_VRM_Material : JsonSerializableBase
{
public string name;
public string shader;
public int renderQueue = -1;
public Dictionary<string, float> floatProperties = new Dictionary<string, float>();
public Dictionary<string, float[]> vectorProperties = new Dictionary<string, float[]>();
public Dictionary<string, int> textureProperties = new Dictionary<string, int>();
public Dictionary<string, bool> keywordMap = new Dictionary<string, bool>();
public Dictionary<string, string> tagMap = new Dictionary<string, string>();
static readonly string[] TAGS = new string[]{
"RenderType",
// "Queue",
};
protected override void SerializeMembers(GLTFJsonFormatter f)
{
f.KeyValue(() => name);
f.KeyValue(() => renderQueue);
f.KeyValue(() => shader);
{
f.Key("floatProperties"); f.BeginMap();
foreach (var kv in floatProperties)
{
f.Key(kv.Key); f.Value(kv.Value);
}
f.EndMap();
}
{
f.Key("vectorProperties"); f.BeginMap();
foreach (var kv in vectorProperties)
{
f.Key(kv.Key); f.Value(kv.Value.ToArray());
}
f.EndMap();
}
{
f.Key("textureProperties"); f.BeginMap();
foreach (var kv in textureProperties)
{
f.Key(kv.Key); f.Value(kv.Value);
}
f.EndMap();
}
{
f.Key("keywordMap"); f.BeginMap();
foreach (var kv in keywordMap)
{
f.Key(kv.Key); f.Value(kv.Value);
}
f.EndMap();
}
{
f.Key("tagMap"); f.BeginMap();
foreach (var kv in tagMap)
{
f.Key(kv.Key); f.Value(kv.Value);
}
f.EndMap();
}
}
public static List<glTF_VRM_Material> Parse(string src)
{
var json = UniJSON.JsonParser.Parse(src)["extensions"]["VRM"]["materialProperties"];
var materials = json.DeserializeList<glTF_VRM_Material>();
var jsonItems = json.ArrayItems.ToArray();
for (int i = 0; i < materials.Count; ++i)
{
materials[i].floatProperties =
jsonItems[i]["floatProperties"].ObjectItems.ToDictionary(x => x.Key, x => x.Value.Value.GetSingle());
materials[i].vectorProperties =
jsonItems[i]["vectorProperties"].ObjectItems.ToDictionary(x => x.Key, x =>
{
return x.Value.ArrayItems.Select(y => y.Value.GetSingle()).ToArray();
});
materials[i].keywordMap =
jsonItems[i]["keywordMap"].ObjectItems.ToDictionary(x => x.Key, x => x.Value.GetBoolean());
materials[i].tagMap =
jsonItems[i]["tagMap"].ObjectItems.ToDictionary(x => x.Key, x => x.Value.GetString());
materials[i].textureProperties =
jsonItems[i]["textureProperties"].ObjectItems.ToDictionary(x => x.Key, x => x.Value.GetInt32());
}
return materials;
}
public static glTF_VRM_Material CreateFromMaterial(Material m, List<Texture> textures)
{
var material = new glTF_VRM_Material
{
name = m.name,
shader = m.shader.name,
renderQueue = m.renderQueue,
};
var prop = VRMPreShaderPropExporter.GetPropsForSupportedShader(m.shader.name);
if (prop == null)
{
#if UNITY_EDITOR
// fallback
Debug.LogWarningFormat("Unsupported shader: {0}", m.shader.name);
prop = VRMPreShaderPropExporter.ShaderProps.FromShader(m.shader);
#endif
}
if (prop == null)
{
Debug.LogWarningFormat("Fail to export shader: {0}", m.shader.name);
}
else
{
// get properties
//material.SetProp(prop);
foreach (var kv in prop.Properties)
{
switch (kv.Value)
{
case VRMPreShaderPropExporter.ShaderPropertyType.Color:
{
var value = m.GetColor(kv.Key).ToArray();
material.vectorProperties.Add(kv.Key, value);
}
break;
case VRMPreShaderPropExporter.ShaderPropertyType.Range:
case VRMPreShaderPropExporter.ShaderPropertyType.Float:
{
var value = m.GetFloat(kv.Key);
material.floatProperties.Add(kv.Key, value);
}
break;
case VRMPreShaderPropExporter.ShaderPropertyType.TexEnv:
{
var texture = m.GetTexture(kv.Key);
if (texture != null)
{
var value = textures.IndexOf(texture);
if (value == -1)
{
Debug.LogFormat("not found {0}", texture.name);
}
else
{
material.textureProperties.Add(kv.Key, value);
}
}
// offset & scaling
var offset = m.GetTextureOffset(kv.Key);
var scaling = m.GetTextureScale(kv.Key);
material.vectorProperties.Add(kv.Key,
new float[] { offset.x, offset.y, scaling.x, scaling.y });
}
break;
case VRMPreShaderPropExporter.ShaderPropertyType.Vector:
{
var value = m.GetVector(kv.Key).ToArray();
material.vectorProperties.Add(kv.Key, value);
}
break;
default:
throw new NotImplementedException();
}
}
}
foreach (var keyword in m.shaderKeywords)
{
material.keywordMap.Add(keyword, m.IsKeywordEnabled(keyword));
}
foreach (var tag in TAGS)
{
var value = m.GetTag(tag, false);
if (!String.IsNullOrEmpty(value))
{
material.tagMap.Add(tag, value);
}
}
return material;
}
}
}