Exemplo n.º 1
0
        //--------------------------------------------------------------
        #region Methods
        //--------------------------------------------------------------

        private void EnsurePreprocessingData()
        {
            if (_preprocessData == null)
            {
                _preprocessData = new PreprocessingData();
            }
        }
 private void Init(params string[] zips)
 {
     _zips.AddAll(zips);
     _sut = new PreprocessingData(_zips);
 }
Exemplo n.º 3
0
        /// <summary>
        /// Prepares this animation for runtime usage. (Must be called after all key frames have been
        /// added!)
        /// </summary>
        /// <remarks>
        /// <para>
        /// <see cref="Freeze"/> must be called after all key frames have been added (see method
        /// <see cref="AddKeyFrame"/>) and before the animation can be used in the animation system.
        /// <see cref="Freeze"/> optimizes the internal data for fast access at runtime.
        /// </para>
        /// <para>
        /// When key frames are added or removed after calling <see cref="Freeze"/>, the animation is
        /// automatically reset into an editable state. All internal optimizations will be discarded!
        /// <see cref="Freeze"/> needs to be called again after all key frames are added/removed.
        /// </para>
        /// <para>
        /// Weights can be modified before and after <see cref="Freeze"/>. For example, weights can be
        /// modified while the animation is running.
        /// </para>
        /// </remarks>
        /// <seealso cref="IsFrozen"/>
        public void Freeze()
        {
            if (IsFrozen)
            {
                return;
            }

            // Desired memory layout to maximize read performance at runtime:
            //   _times
            //   _channels
            //   _weights
            //   _indices
            //   _keyFrameTypes
            //   _keyFrames

            // ----- Process channels and initialize array of key frame times (_times) and bone indices (_channels).
            var times    = new List <TimeSpan>();
            var channels = new List <int>();

            if (_preprocessData != null)
            {
                foreach (var item in _preprocessData.Channels)
                {
                    int boneIndex = item.Key;
                    var keyFrames = item.Value;

                    // Ignore empty channels.
                    if (keyFrames == null || keyFrames.Count <= 0)
                    {
                        continue;
                    }

                    // Sort key frames.
                    keyFrames.Sort(CompareKeyFrameTime);

                    // Create a list of all key frame times.
                    foreach (var keyFrame in keyFrames)
                    {
                        times.Add(keyFrame.Time);
                    }

                    // Update total duration.
                    _totalDuration = AnimationHelper.Max(_totalDuration, keyFrames[keyFrames.Count - 1].Time);

                    // Create a list of all bone indices.
                    channels.Add(boneIndex);
                }
            }

            // Sort key frame times and remove duplicates.
            times.Sort();
            var timesCompacted = new List <TimeSpan>();
            var lastTime       = TimeSpan.MinValue;

            foreach (var time in times)
            {
                if (time > lastTime)
                {
                    timesCompacted.Add(time);
                    lastTime = time;
                }
            }

            _times = timesCompacted.ToArray();

            // Sort bone indices.
            channels.Sort();
            _channels = channels.ToArray();
            int numberOfChannels = channels.Count;

            // ----- Initialize array of bone weights (_weights).
            _weights = new float[numberOfChannels];
            for (int channelIndex = 0; channelIndex < numberOfChannels; channelIndex++)
            {
                Debug.Assert(_preprocessData != null, "If _preprocessData is null, the number of channels should be 0.");

                int boneIndex = _channels[channelIndex];

                float weight;
                if (!_preprocessData.Weights.TryGetValue(boneIndex, out weight))
                {
                    weight = 1;
                }

                _weights[channelIndex] = weight;
            }

            // ----- Create indices for fast lookup (_indices).
            _indices = new int[numberOfChannels * _times.Length];
            for (int channelIndex = 0; channelIndex < numberOfChannels; channelIndex++)
            {
                Debug.Assert(_preprocessData != null, "If _preprocessData is null, the number of channels should be 0.");

                int boneIndex     = _channels[channelIndex];
                var keyFrames     = _preprocessData.Channels[boneIndex];
                int keyFrameIndex = 0;
                for (int timeIndex = 0; timeIndex < _times.Length; timeIndex++)
                {
                    TimeSpan time = _times[timeIndex];

                    int nextIndex = keyFrameIndex + 1;
                    while (nextIndex < keyFrames.Count && keyFrames[nextIndex].Time <= time)
                    {
                        nextIndex++;
                    }

                    // Now nextIndex points to the first key frame with a larger time. We must use
                    // the previous key frame.
                    keyFrameIndex = nextIndex - 1;
                    _indices[timeIndex * numberOfChannels + channelIndex] = keyFrameIndex;
                }
            }

            // ----- Initialize the key frame lists (_keyFrameTypes, _keyFrames).
            _keyFrameTypes = new BoneKeyFrameType[numberOfChannels];
            _keyFrames     = new object[numberOfChannels];

            // One iteration for each bone channel.
            for (int channelIndex = 0; channelIndex < numberOfChannels; channelIndex++)
            {
                Debug.Assert(_preprocessData != null, "If _preprocessData is null, the number of channels should be 0.");

                int boneIndex = _channels[channelIndex];
                var keyFrames = _preprocessData.Channels[boneIndex];

                // Check if we need Scale.
                bool isScaleUsed = false;
                foreach (var keyFrame in keyFrames)
                {
                    if (keyFrame.Transform.HasScale)
                    {
                        isScaleUsed = true;
                        break;
                    }
                }

                // Check if we need Translation.
                bool isTranslationUsed = false;
                foreach (var keyFrame in keyFrames)
                {
                    if (keyFrame.Transform.HasTranslation)
                    {
                        isTranslationUsed = true;
                        break;
                    }
                }

                // Add key frames depending on the type.
                if (!isScaleUsed && !isTranslationUsed)
                {
                    // R
                    _keyFrameTypes[channelIndex] = BoneKeyFrameType.R;
                    var compactKeyFrames = new BoneKeyFrameR[keyFrames.Count];
                    for (int keyFrameIndex = 0; keyFrameIndex < compactKeyFrames.Length; keyFrameIndex++)
                    {
                        compactKeyFrames[keyFrameIndex] = new BoneKeyFrameR
                        {
                            Time     = keyFrames[keyFrameIndex].Time,
                            Rotation = keyFrames[keyFrameIndex].Transform.Rotation,
                        };
                    }

                    _keyFrames[channelIndex] = compactKeyFrames;
                }
                else if (isScaleUsed)
                {
                    // SRT
                    _keyFrameTypes[channelIndex] = BoneKeyFrameType.SRT;

                    // (Cache optimization: The preprocessing data already contains SRT key frames,
                    // but we still copy the key frames because we want all data to be aligned in
                    // memory.)
                    _keyFrames[channelIndex] = keyFrames.ToArray();
                }
                else
                {
                    // RT
                    _keyFrameTypes[channelIndex] = BoneKeyFrameType.RT;
                    var compactKeyFrames = new BoneKeyFrameRT[keyFrames.Count];
                    for (int keyFrameIndex = 0; keyFrameIndex < compactKeyFrames.Length; keyFrameIndex++)
                    {
                        compactKeyFrames[keyFrameIndex] = new BoneKeyFrameRT
                        {
                            Time        = keyFrames[keyFrameIndex].Time,
                            Rotation    = keyFrames[keyFrameIndex].Transform.Rotation,
                            Translation = keyFrames[keyFrameIndex].Transform.Translation,
                        };
                    }

                    _keyFrames[channelIndex] = compactKeyFrames;
                }
            }

            // Free memory of preprocessing structures.
            _preprocessData = null;
        }
Exemplo n.º 4
0
        private void Initialize()
        {
            var zips = _io.FindRelativeZipPaths();

            _data = new PreprocessingData(zips);
        }