【发布时间】:2019-03-04 12:23:13
【问题描述】:
我有一个包含 12 个混合形状的面部模型,其中每个混合形状只是 0(中性面部表情)和 1(最大激活表情)之间的浮点值列表,但是我只从前 2 个混合形状开始;即现在只有两个列表,比如微笑和怀疑的表情。
我的目的是浏览这两个列表中所有项目的所有可能组合,并制作面部动作的镜头(电影剪辑),以显示 blendshape 值/权重的所有可能组合的样子。
所以,我写了以下内容来简化这个场景,目前只有两个 blendshapes,并在应用程序关闭后立即将它们保存到文件中:
public class BlendShapesVAL : MonoBehaviour
{
private List<float> _weightValues_Preset1_smile = new List<float>();
private List<float> _weightValues_Preset2_skeptic = new List<float>();
public bool _TransitionAnimation = true;
public float _TransitionAnimationSpeed = 2f;
public BlendShapesPresetController _BSPC;
private List<float> _weightsList = new List<float>();
public List<bool> _ActivationsList = new List<bool>();
public List<string> _PresetsNamesList = new List<string>();
private void Awake()
{
_weightsList.Clear();
_ActivationsList.Clear();
for (int i = 0; i < _PresetsNamesList.Count; ++i)
{
_ActivationsList.Add(false);
_weightsList.Add(0);
}
}
private void Start()
{
if (_BSPC != null)
{
// . . .
}
else
{
_BSPC = GetComponent<BlendShapesPresetController>();
}
StartCoroutine("Interpolate");
}
/// <summary>
/// Writes (i.e. saves) blendshape values to file when the application quits.
/// </summary>
///
private void OnApplicationQuit()
{
SaveBlendShapesValues(_weightValues_Preset1_smile);
SaveBlendShapesValues(_weightValues_Preset2_skeptic);
PlayerPrefs.DeleteAll();
}
/// <summary>
/// Goes thorugh all the possible combinations of blendshape weights.
/// For now, only the first two though!
/// </summary>
///
private IEnumerator Interpolate()
{
for (int i = 0; i <= 100; i++)
{
float weightValuesmile = (float)i / 100.0f;
_BSPC.SetWeight("Preset1_smile", weightValuesmile);
_weightValues_Preset1_smile.Add(weightValuesmile);
for (int j = 0; j <= 100; j++)
{
float weightValueSkeptic = (float)j / 100.0f;
_BSPC.SetWeight("Preset2_skeptic", weightValueSkeptic);
_weightValues_Preset2_skeptic.Add(weightValueSkeptic);
}
yield return null;
}
}
/// <summary>
/// Writes (i.e. saves) blendshape values to file.
/// <param name="blendShapesValuesFilePath">
/// The path to the file that will store the list of float values;
/// i.e. "Application.dataPath" plus the name of the CSV file.
/// </param>
/// <param name="values">
/// The float values that are the blendshape weights.
/// </param>
/// </summary>
///
private static void SaveBlendShapesValues(List<float> values)
{
List<string> lines = new List<string>
{
/// Add a header row for the labels.
"TimeStamp,Preset1_smile,Preset2_skeptic"
};
foreach (var value in values)
{
/// Iterate through all the elements.
lines.Add(DateTime.Now + "," + value);
}
/// Load the old counter.
int counter = PlayerPrefs.GetInt("_counter_", 0);
/// Concatenate the file name constituents and combine it with the application data path.
string fileName = string.Format("BlendShapesValues_{0}.csv", counter.ToString() );
string tempPath = Path.Combine(Application.dataPath, fileName);
try
{
File.WriteAllLines(tempPath, lines.ToArray() );
Debug.Log("Saved blendshape weight values to: " + tempPath);
/// Increment the counter.
counter++;
/// Save the current counter.
PlayerPrefs.SetInt("_counter_", counter);
PlayerPrefs.Save();
}
catch (Exception e)
{
Debug.LogWarning("Failed to save to PlayerPrefs: " + tempPath);
Debug.LogWarning("Error: " + e.Message);
}
}
}
在 Unity 编辑器中,混合形状的值显示为 0 到 100,因此我在代码中进行了转换,如下图所示:
第一个文件有 101 个值(0...100 加上列标签的顶行)在此屏幕截图中可以看到一个 sn-p:
第二个文件有 10201 值。我的第一个问题是这种在应用程序停止后将迭代值保存到文件的方法是否是一个好的解决方案,因为随着我添加更多列表(即 blendshapes),值会大幅增长?
我的第二个问题是如何减慢迭代速度,因为(在第一个屏幕截图中)微笑值开始从 0 计数到 100 并且我可以看到它们(脸部缓慢移动一种可见的方式),但在发生这种情况时,我注意到第二个列表(怀疑论者)显然立即跳到 100,所以它完成得如此之快以至于它无法被 Win 屏幕录像机记录......
【问题讨论】: