Перебирая все возможные комбинации нескольких элементов списка - PullRequest
0 голосов
/ 04 марта 2019

У меня есть модель лица с 12 blendshape, где каждая blendshape - это просто список значений с плавающей точкой между 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, поэтому мое преобразование в коде, как показано на снимке экрана:

enter image description here

Первый файл имеет значения 101 (0 ... 100 плюс верхняя строка для меток столбцов), на этом скриншоте можно увидеть фрагмент:

enter image description here

Второй файл имеет значения 10201 .Мой первый вопрос - является ли этот метод сохранения повторяющихся значений в файл после остановки приложения хорошим решением, учитывая значительный рост значений при добавлении новых списков (т. Е. Blendshapes)?

Мой Второй вопрос - как я могу замедлить итерации, потому что (на первом скриншоте) значения улыбки начинают отсчитываться от 0 до 100, и я вижу их (лицо медленно перемещается в видимомно, как это происходит, я замечаю, что второй список (скептик), по-видимому, сразу переходит на 100, так что это делается так быстро, что он не может быть записан устройством записи экрана Win ...

1 Ответ

0 голосов
/ 04 марта 2019

Ну, я не был уверен, может ли это быть комментарий или ответ, поэтому дайте мне знать, если я что-то упустил.

На ваш первый вопрос, если вы согласны с тем, что сохраненные файлы не читаютсялюдей я бы предложил использовать BinaryReader.Потому что размер сохраненных файлов будет меньше, и когда вы захотите прочитать их обратно, чтобы сделать ваш клип, он будет читать его быстрее.Кроме того, учитывая, что вы хотите иметь 12 смешанных фигур и их комбинацию, этот файл может быть огромным.

Для вашего второго вопроса итерация переходит к 100, потому что вы уступаете только после завершения внутреннего цикла.Поэтому в каждом кадре 100 комбинаций скептиков для 1 улыбки добавляются в список.Я бы порекомендовал использовать многопоточность или систему заданий Unity для такой задачи, потому что это может быть вычислительно дорогостоящим с 12 смешанными формами и всеми комбинациями.

Дайте мне знать, если я могу помочь в дальнейшем.Удачи!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...