96 lines
3.5 KiB
C#
Raw Permalink Normal View History

#region Using Statements
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
#endregion
// This file is part of the ANX.Framework created by the
// "ANX.Framework developer group" and released under the Ms-PL license.
// For details see: http://anxframework.codeplex.com/license
namespace ANX.Framework.Content.Pipeline.Graphics
{
public class BoneWeightCollection : Collection<BoneWeight>
{
public BoneWeightCollection()
: base(new List<BoneWeight>())
{
}
/// <summary>
/// Normalizes the contents of the bone weights list.
/// </summary>
/// <remarks>
/// Normalization does the following:
/// <list type="bullet">
/// <item>Sorts weights such that the most significant weight is first.</item>
/// <item>Removes zero-value entries.</item>
/// <item>Discards weights with the smallest value until there are maxWeights or less in the list.</item>
/// <item>Adjusts values so the sum equals one.</item>
/// </list>
/// </remarks>
/// <exception cref="System.InvalidContentException">Gets thrown if all weights are zero.</exception>
/// <exception cref="System.ArgumentOutOfRangeException">Gets thrown if maxWeights less or equal to zero.</exception>
public void NormalizeWeights()
{
this.NormalizeWeights(int.MaxValue);
}
/// <summary>
/// Normalizes the contents of the bone weights list.
/// </summary>
/// <remarks>
/// Normalization does the following:
/// <list type="bullet">
/// <item>Sorts weights such that the most significant weight is first.</item>
/// <item>Removes zero-value entries.</item>
/// <item>Discards weights with the smallest value until there are maxWeights or less in the list.</item>
/// <item>Adjusts values so the sum equals one.</item>
/// </list>
/// </remarks>
/// <param name="maxWeights">Maximum number of weights allowed.</param>
/// <exception cref="System.InvalidContentException">Gets thrown if all weights are zero.</exception>
/// <exception cref="System.ArgumentOutOfRangeException">Gets thrown if maxWeights less or equal to zero.</exception>
public void NormalizeWeights(int maxWeights)
{
if (maxWeights <= 0)
throw new ArgumentOutOfRangeException("maxWeights");
((List<BoneWeight>)Items).Sort((left, right) => right.Weight.CompareTo(left.Weight));
float accumulatedValue = 0f;
for (int i = 0; i < Count; i++)
{
var weight = Items[i].Weight;
if (weight <= 0f || i >= maxWeights)
{
this.RemoveAt(i);
i--;
}
else
{
accumulatedValue += weight;
}
}
if (accumulatedValue == 0f)
{
throw new InvalidContentException(string.Format("All weights are zero."));
}
if (accumulatedValue != 0f)
{
for (int i = 0; i < Count; i++)
{
this[i] = new BoneWeight(this[i].BoneName, accumulatedValue / this[i].Weight);
}
}
}
}
}