Cleanup BlendShapeMerger. Removed BlendShapeMerger.Clear

This commit is contained in:
ousttrue 2018-11-03 16:14:13 +09:00
parent caf215ca2a
commit 7a95cd07ab
7 changed files with 322 additions and 213 deletions

View File

@ -0,0 +1,105 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace VRM
{
///
/// A.Value * A.Weight + B.Value * B.Weight ...
///
class BlendShapeBindingMerger
{
/// <summary>
/// BlendShapeの適用値を蓄積する
/// </summary>
/// <typeparam name="BlendShapeBinding"></typeparam>
/// <typeparam name="float"></typeparam>
/// <returns></returns>
Dictionary<BlendShapeBinding, float> m_blendShapeValueMap = new Dictionary<BlendShapeBinding, float>();
/// <summary>
///
/// </summary>
/// <returns></returns>
Dictionary<BlendShapeBinding, Action<float>> m_blendShapeSetterMap = new Dictionary<BlendShapeBinding, Action<float>>();
public BlendShapeBindingMerger(Dictionary<BlendShapeKey, BlendShapeClip> clipMap, Transform root)
{
foreach (var kv in clipMap)
{
foreach (var binding in kv.Value.Values)
{
if (!m_blendShapeSetterMap.ContainsKey(binding))
{
var _target = root.Find(binding.RelativePath);
SkinnedMeshRenderer target = null;
if (_target != null)
{
target = _target.GetComponent<SkinnedMeshRenderer>();
}
if (target != null)
{
if (binding.Index >= 0 && binding.Index < target.sharedMesh.blendShapeCount)
{
m_blendShapeSetterMap.Add(binding, x =>
{
target.SetBlendShapeWeight(binding.Index, x);
});
}
else
{
Debug.LogWarningFormat("Invalid blendshape binding: {0}: {1}", target.name, binding);
}
}
else
{
Debug.LogWarningFormat("SkinnedMeshRenderer: {0} not found", binding.RelativePath);
}
}
}
}
}
public void ImmediatelySetValue(BlendShapeClip clip, float value)
{
foreach (var binding in clip.Values)
{
Action<float> setter;
if (m_blendShapeSetterMap.TryGetValue(binding, out setter))
{
setter(binding.Weight * value);
}
}
}
public void AccumulateValue(BlendShapeClip clip, float value)
{
foreach (var binding in clip.Values)
{
float acc;
if (m_blendShapeValueMap.TryGetValue(binding, out acc))
{
m_blendShapeValueMap[binding] = acc + binding.Weight * value;
}
else
{
m_blendShapeValueMap[binding] = binding.Weight * value;
}
}
}
public void Apply()
{
foreach (var kv in m_blendShapeValueMap)
{
Action<float> setter;
if (m_blendShapeSetterMap.TryGetValue(kv.Key, out setter))
{
setter(kv.Value);
}
}
m_blendShapeValueMap.Clear();
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: ca4c8446451eeed46b1598db9e08bb73
timeCreated: 1541229189
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -7,161 +7,38 @@ using UnityEngine;
namespace VRM
{
/// <summary>
/// ブレンドシェイプを蓄えてまとめて適用するクラス
/// </summary>
class BlendShapeMerger
{
/// <summary>
/// KeyからBlendShapeClipを得る
/// Key からBlendShapeClipを得る
/// </summary>
Dictionary<BlendShapeKey, BlendShapeClip> m_clipMap;
/// <summary>
/// BlendShapeのWeightを蓄積する
/// BlendShape のWeightを記録する
/// </summary>
Dictionary<BlendShapeKey, float> m_valueMap;
/// <summary>
/// 名前とmaterialのマッピング
/// </summary>
Dictionary<string, Material> m_materialMap;
BlendShapeBindingMerger m_blendShapeBindingMerger;
/// <summary>
/// BlendShapeの適用値を蓄積する
/// </summary>
/// <typeparam name="BlendShapeBinding"></typeparam>
/// <typeparam name="float"></typeparam>
/// <returns></returns>
Dictionary<BlendShapeBinding, float> m_blendShapeValueMap = new Dictionary<BlendShapeBinding, float>();
MaterialValueBindingMerger m_materialValueBindingMerger;
/// <summary>
///
/// </summary>
/// <returns></returns>
Dictionary<BlendShapeBinding, Action<float>> m_blendShapeSetterMap = new Dictionary<BlendShapeBinding, Action<float>>();
/// <summary>
/// MaterialValueの適用値を蓄積する
/// </summary>
/// <typeparam name="MaterialValueBinding"></typeparam>
/// <typeparam name="float"></typeparam>
/// <returns></returns>
Dictionary<MaterialValueBinding, float> m_materialValueMap = new Dictionary<MaterialValueBinding, float>();
Dictionary<MaterialValueBinding, Action<float>> m_materialSetterMap = new Dictionary<MaterialValueBinding, Action<float>>();
public BlendShapeMerger(IEnumerable<BlendShapeClip> clips, Transform root)
{
m_materialMap = new Dictionary<string, Material>();
foreach (var x in root.Traverse())
{
var renderer = x.GetComponent<Renderer>();
if (renderer != null)
{
foreach (var y in renderer.sharedMaterials.Where(y => y != null))
{
if (!string.IsNullOrEmpty(y.name))
{
if (!m_materialMap.ContainsKey(y.name))
{
m_materialMap.Add(y.name, y);
}
}
}
}
}
m_clipMap = clips.ToDictionary(x => BlendShapeKey.CreateFrom(x), x => x);
m_valueMap = new Dictionary<BlendShapeKey, float>();
foreach (var kv in m_clipMap)
{
foreach (var binding in kv.Value.Values)
{
if (!m_blendShapeSetterMap.ContainsKey(binding))
{
var _target = root.Find(binding.RelativePath);
SkinnedMeshRenderer target = null;
if (_target != null)
{
target = _target.GetComponent<SkinnedMeshRenderer>();
}
if (target != null)
{
if (binding.Index >= 0 && binding.Index < target.sharedMesh.blendShapeCount)
{
m_blendShapeSetterMap.Add(binding, x =>
{
target.SetBlendShapeWeight(binding.Index, x);
});
}
else
{
Debug.LogWarningFormat("Invalid blendshape binding: {0}: {1}", target.name, binding);
}
}
else
{
Debug.LogWarningFormat("SkinnedMeshRenderer: {0} not found", binding.RelativePath);
}
}
}
foreach (var binding in kv.Value.MaterialValues)
{
if (!m_materialSetterMap.ContainsKey(binding))
{
Material target;
if (m_materialMap.TryGetValue(binding.MaterialName, out target))
{
if (binding.ValueName.EndsWith("_ST_S"))
{
var valueName = binding.ValueName.Substring(0, binding.ValueName.Length - 2);
Action<float> setter = value =>
{
var propValue = binding.BaseValue + (binding.TargetValue - binding.BaseValue) * value;
var src = target.GetVector(valueName);
src.x = propValue.x; // horizontal only
src.z = propValue.z; // horizontal only
target.SetVector(valueName, src);
};
m_materialSetterMap.Add(binding, setter);
}
else if (binding.ValueName.EndsWith("_ST_T"))
{
var valueName = binding.ValueName.Substring(0, binding.ValueName.Length - 2);
Action<float> setter = value =>
{
var propValue = binding.BaseValue + (binding.TargetValue - binding.BaseValue) * value;
var src = target.GetVector(valueName);
src.y = propValue.y; // vertical only
src.w = propValue.w; // vertical only
target.SetVector(valueName, src);
};
m_materialSetterMap.Add(binding, setter);
}
else
{
Action<float> vec4Setter = x =>
{
var propValue = binding.BaseValue + (binding.TargetValue - binding.BaseValue) * x;
target.SetColor(binding.ValueName, propValue);
};
m_materialSetterMap.Add(binding, vec4Setter);
}
}
else
{
Debug.LogWarningFormat("material: {0} not found", binding.MaterialName);
}
}
}
}
m_blendShapeBindingMerger = new BlendShapeBindingMerger(m_clipMap, root);
m_materialValueBindingMerger = new MaterialValueBindingMerger(m_clipMap, root);
}
/*
public void Clear()
{
foreach (var kv in m_valueMap.ToArray())
@ -170,31 +47,15 @@ namespace VRM
}
Apply();
}
*/
/// <summary>
/// 蓄積した値を適用する
/// </summary>
public void Apply()
{
foreach (var kv in m_blendShapeValueMap)
{
Action<float> setter;
if (m_blendShapeSetterMap.TryGetValue(kv.Key, out setter))
{
setter(kv.Value);
}
}
m_blendShapeValueMap.Clear();
foreach (var kv in m_materialValueMap)
{
Action<float> setter;
if (m_materialSetterMap.TryGetValue(kv.Key, out setter))
{
setter(kv.Value);
}
}
m_materialValueMap.Clear();
m_blendShapeBindingMerger.Apply();
m_materialValueBindingMerger.Apply();
}
/// <summary>
@ -230,33 +91,8 @@ namespace VRM
value = Mathf.Round(value);
}
foreach (var binding in clip.Values)
{
// 積算
float acc;
if (m_blendShapeValueMap.TryGetValue(binding, out acc))
{
m_blendShapeValueMap[binding] = acc + binding.Weight * value;
}
else
{
m_blendShapeValueMap[binding] = binding.Weight * value;
}
}
foreach (var binding in clip.MaterialValues)
{
// 積算
float acc;
if (m_materialValueMap.TryGetValue(binding, out acc))
{
m_materialValueMap[binding] = acc + value;
}
else
{
m_materialValueMap[binding] = value;
}
}
m_blendShapeBindingMerger.AccumulateValue(clip, value);
m_materialValueBindingMerger.AccumulateValue(clip, value);
}
/// <summary>
@ -279,23 +115,8 @@ namespace VRM
value = Mathf.Round(value);
}
foreach (var binding in clip.Values)
{
Action<float> setter;
if (m_blendShapeSetterMap.TryGetValue(binding, out setter))
{
setter(binding.Weight * value);
}
}
foreach (var binding in clip.MaterialValues)
{
Action<float> setter;
if (m_materialSetterMap.TryGetValue(binding, out setter))
{
setter(value);
}
}
m_blendShapeBindingMerger.ImmediatelySetValue(clip, value);
m_materialValueBindingMerger.ImmediatelySetValue(clip, value);
}
public void SetValue(BlendShapeKey key, float value, bool replace)
@ -322,25 +143,7 @@ namespace VRM
public void RestoreMaterialInitialValues(IEnumerable<BlendShapeClip> clips)
{
if (m_materialMap != null)
{
foreach (var x in clips)
{
foreach (var y in x.MaterialValues)
{
// restore values
Material material;
if (m_materialMap.TryGetValue(y.MaterialName, out material))
{
material.SetColor(y.ValueName, y.BaseValue);
}
else
{
Debug.LogWarningFormat("{0} not found", y.MaterialName);
}
}
}
}
m_materialValueBindingMerger.RestoreMaterialInitialValues(clips);
}
}
}

View File

@ -7,6 +7,9 @@ namespace VRM
{
public static class BlendShapeClipEditorHelper
{
///
/// BlendShape List のElement描画
///
public static bool DrawBlendShapeBinding(Rect position, SerializedProperty property,
PreviewSceneManager scene)
{
@ -41,6 +44,9 @@ namespace VRM
return changed;
}
///
/// Material List のElement描画
///
public static bool DrawMaterialValueBinding(Rect position, SerializedProperty property,
PreviewSceneManager scene)
{

View File

@ -0,0 +1,169 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UniGLTF;
namespace VRM
{
///
/// Base + (A.Target - Base) * A.Weight + (B.Target - Base) * B.Weight ...
///
class MaterialValueBindingMerger
{
/// <summary>
/// 名前とmaterialのマッピング
/// </summary>
Dictionary<string, Material> m_materialMap;
/// <summary>
/// MaterialValueの適用値を蓄積する
/// </summary>
/// <typeparam name="MaterialValueBinding"></typeparam>
/// <typeparam name="float"></typeparam>
/// <returns></returns>
Dictionary<MaterialValueBinding, float> m_materialValueMap = new Dictionary<MaterialValueBinding, float>();
Dictionary<MaterialValueBinding, Action<float>> m_materialSetterMap = new Dictionary<MaterialValueBinding, Action<float>>();
public MaterialValueBindingMerger(Dictionary<BlendShapeKey, BlendShapeClip> clipMap, Transform root)
{
m_materialMap = new Dictionary<string, Material>();
foreach (var x in root.Traverse())
{
var renderer = x.GetComponent<Renderer>();
if (renderer != null)
{
foreach (var y in renderer.sharedMaterials.Where(y => y != null))
{
if (!string.IsNullOrEmpty(y.name))
{
if (!m_materialMap.ContainsKey(y.name))
{
m_materialMap.Add(y.name, y);
}
}
}
}
}
foreach (var kv in clipMap)
{
foreach (var binding in kv.Value.MaterialValues)
{
if (!m_materialSetterMap.ContainsKey(binding))
{
Material target;
if (m_materialMap.TryGetValue(binding.MaterialName, out target))
{
if (binding.ValueName.EndsWith("_ST_S"))
{
var valueName = binding.ValueName.Substring(0, binding.ValueName.Length - 2);
Action<float> setter = value =>
{
var propValue = binding.BaseValue + (binding.TargetValue - binding.BaseValue) * value;
var src = target.GetVector(valueName);
src.x = propValue.x; // horizontal only
src.z = propValue.z; // horizontal only
target.SetVector(valueName, src);
};
m_materialSetterMap.Add(binding, setter);
}
else if (binding.ValueName.EndsWith("_ST_T"))
{
var valueName = binding.ValueName.Substring(0, binding.ValueName.Length - 2);
Action<float> setter = value =>
{
var propValue = binding.BaseValue + (binding.TargetValue - binding.BaseValue) * value;
var src = target.GetVector(valueName);
src.y = propValue.y; // vertical only
src.w = propValue.w; // vertical only
target.SetVector(valueName, src);
};
m_materialSetterMap.Add(binding, setter);
}
else
{
Action<float> vec4Setter = x =>
{
var propValue = binding.BaseValue + (binding.TargetValue - binding.BaseValue) * x;
target.SetColor(binding.ValueName, propValue);
};
m_materialSetterMap.Add(binding, vec4Setter);
}
}
else
{
Debug.LogWarningFormat("material: {0} not found", binding.MaterialName);
}
}
}
}
}
public void RestoreMaterialInitialValues(IEnumerable<BlendShapeClip> clips)
{
if (m_materialMap != null)
{
foreach (var x in clips)
{
foreach (var y in x.MaterialValues)
{
// restore values
Material material;
if (m_materialMap.TryGetValue(y.MaterialName, out material))
{
material.SetColor(y.ValueName, y.BaseValue);
}
else
{
Debug.LogWarningFormat("{0} not found", y.MaterialName);
}
}
}
}
}
public void ImmediatelySetValue(BlendShapeClip clip, float value)
{
foreach (var binding in clip.MaterialValues)
{
Action<float> setter;
if (m_materialSetterMap.TryGetValue(binding, out setter))
{
setter(value);
}
}
}
public void AccumulateValue(BlendShapeClip clip, float value)
{
foreach (var binding in clip.MaterialValues)
{
// 積算
float acc;
if (m_materialValueMap.TryGetValue(binding, out acc))
{
m_materialValueMap[binding] = acc + value;
}
else
{
m_materialValueMap[binding] = value;
}
}
}
public void Apply()
{
foreach (var kv in m_materialValueMap)
{
Action<float> setter;
if (m_materialSetterMap.TryGetValue(kv.Key, out setter))
{
setter(kv.Value);
}
}
m_materialValueMap.Clear();
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 4ccc88d77d5d1e74499d053083ade08d
timeCreated: 1541229189
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -159,6 +159,7 @@ namespace VRM
}
}
/*
/// <summary>
/// Clear all blendShape values
/// </summary>
@ -169,6 +170,7 @@ namespace VRM
m_merger.Clear();
}
}
*/
/// <summary>
/// Apply blendShape values that use SetValue apply=false