using Microsoft.Xna.Framework;
using DWORD = System.UInt32;

namespace MikuMikuDance.XNA.Motion.MotionData
{
    /// <summary>
    /// ベジェ曲線
    /// </summary>
    public class BezierCurve
    {
        internal const float Epsilon = 1.0e-3f;
        /// <summary>
        /// ベジェ曲線に用いる点１
        /// </summary>
        public Vector2 v1 { get; set; }
        /// <summary>
        /// ベジェ曲線に用いる点2
        /// </summary>
        public Vector2 v2 { get; set; }
        /// <summary>
        /// 進行度合から移行度合を取得
        /// </summary>
        /// <param name="Progress">進行度合</param>
        /// <returns>移行度合</returns>
        public float Evaluate(float Progress)
        {
            //ニュートン法による近似
            float t = MathHelper.Clamp(Progress, 0, 1);
            float dt;
            do
            {
                dt = -(fx(t)-Progress) / dfx(t);
                if (float.IsNaN(dt))
                    break;
                t += dt;
            } while (dt > Epsilon);
            return fy(t);
        }

        private float fy(float t)
        {
            //fy(t)=(1-t)^3*0+3*(1-t)^2*t*v1.y+3*(1-t)*t^2*v2.y+t^3*1
            return 3 * (1 - t) * (1 - t) * t * v1.Y + 3 * (1 - t) * t * t * v2.Y + t * t * t;
        }

        float fx(float t)
        {
            //fx(t)=(1-t)^3*0+3*(1-t)^2*t*v1.x+3*(1-t)*t^2*v2.x+t^3*1
            return 3 * (1 - t) * (1 - t) * t * v1.X + 3 * (1 - t) * t * t * v2.X + t * t * t;
        }
        float dfx(float t)
        {
            //dfx(t)/dt=-6(1-t)*t*v1.x+3(1-t)^2*v1.x-3t^2*v2.x+6(1-t)*t*v2.x+3t^2
            return -6 * (1 - t) * t * v1.X + 3 * (1 - t) * (1 - t) * v1.X
                - 3 * t * t * v2.X + 6 * (1 - t) * t * v2.X + 3 * t * t;
        }

    }
    /// <summary>
    /// ボーンモーションデータ
    /// </summary>
    public class MMDBoneMotion
    {
        /// <summary>
        /// ボーン名
        /// </summary>
        public string BoneName { get; set; }//[15];
        /// <summary>
        /// フレーム番号
        /// </summary>
        public DWORD FrameNo { get; set; }
        /// <summary>
        /// 位置ベクトル
        /// </summary>
        public Vector3 Location { get; set; }
        /// <summary>
        /// クォータニオン
        /// </summary>
        public Quaternion Quatanion { get; set; }
        /// <summary>
        /// 補完用曲線
        /// </summary>
        public BezierCurve[] Curve { get; set; }
        
        
    }
}
