Ejemplo n.º 1
0
        /// 選択ボーンに対応するウェイトを加算する。
        /// returns: ウェイトを変更したか
        public bool Execute()
        {
            foreach (MqoSkinWeight skin_weight in vertex.skin_weights)
            {
                SkinWeightCommand skin_weight_command = new SkinWeightCommand(skin_weight);
                this.skin_weight_commands.Add(skin_weight_command);
            }
            //処理前の値を記憶する。
            {
                int nskin_weight = 0;
                foreach (MqoSkinWeight skin_weight in vertex.skin_weights)
                {
                    this.skin_weight_commands[nskin_weight].old_attr.bone   = skin_weight.bone;
                    this.skin_weight_commands[nskin_weight].old_attr.weight = skin_weight.weight;
                    nskin_weight++;
                }
            }

            bool updated = false;

            //選択ボーンに対応するウェイトを検索する。
            MqoSkinWeight selected_skin_weight = null;

            foreach (MqoSkinWeight skin_weight in vertex.skin_weights)
            {
                if (skin_weight.bone == selected_node)
                {
                    selected_skin_weight = skin_weight;
                    break;
                }
            }

            bool prepare_bone = false;

            switch (weight_op)
            {
            case WeightOperation.Gain:
                prepare_bone = weight > 0;
                break;

            case WeightOperation.Assign:
                prepare_bone = weight > 0;
                break;
            }

            //選択ボーンに対応するウェイトがなければ、最小値を持つウェイトを置き換える。
            if (selected_skin_weight == null && prepare_bone)
            {
                TSONode bone = selected_node;
                {
                    selected_skin_weight        = vertex.skin_weights[3]; //前提: vertex.skin_weights の要素数は 4 かつ並び順はウェイト値の降順
                    selected_skin_weight.bone   = bone;
                    selected_skin_weight.weight = 0.0f;
                }
            }

            //選択ボーンに対応するウェイトを加算する。
            if (selected_skin_weight != null)
            {
                updated = true;

                float w0 = selected_skin_weight.weight; //変更前の対象ウェイト値
                float m0 = 1.0f - w0;                   //変更前の残りウェイト値
                float w1;                               //変更後の対象ウェイト値
                switch (weight_op)
                {
                case WeightOperation.Gain:
                    w1 = w0 + weight;
                    break;

                case WeightOperation.Reduce:
                    w1 = w0 - weight;
                    break;

                case WeightOperation.Assign:
                    w1 = weight;
                    break;

                default:
                    w1 = w0;
                    break;
                }
                //clamp 0.0f .. 1.0f
                if (w1 > 1.0f)
                {
                    w1 = 1.0f;
                }
                if (w1 < 0.0f)
                {
                    w1 = 0.0f;
                }

                float d1 = w1 - w0; //実際の加算値
                float m1 = 0.0f;    //減算後の残りウェイト値
                if (m0 != 0)
                {
                    //残りウェイトを減算する。
                    foreach (MqoSkinWeight skin_weight in vertex.skin_weights)
                    {
                        if (skin_weight == selected_skin_weight)
                        {
                            continue;
                        }

                        float w2 = skin_weight.weight - skin_weight.weight * d1 / m0;
                        if (w2 < 0.001f)
                        {
                            w2 = 0.0f;//微小ウェイトは捨てる。
                        }
                        skin_weight.weight = w2;
                        m1 += w2;
                    }
                }
                selected_skin_weight.weight = 1.0f - m1;

                Array.Sort(vertex.skin_weights);
            }
#if false
            {
                int nskin_weight = 0;
                foreach (MqoSkinWeight skin_weight in vertex.skin_weights)
                {
                    Console.WriteLine("i:{0} bone:{1} w:{2}", nskin_weight, skin_weight.bone.Name, skin_weight.weight);
                    nskin_weight++;
                }
                Console.WriteLine();
            }
#endif
            //処理後の値を記憶する。
            {
                int nskin_weight = 0;
                foreach (MqoSkinWeight skin_weight in vertex.skin_weights)
                {
                    this.skin_weight_commands[nskin_weight].new_attr.bone   = skin_weight.bone;
                    this.skin_weight_commands[nskin_weight].new_attr.weight = skin_weight.weight;
                    nskin_weight++;
                }
            }
            return(updated);
        }
Ejemplo n.º 2
0
 /// スキンウェイト操作を生成します。
 public SkinWeightCommand(MqoSkinWeight skin_weight)
 {
     this.skin_weight = skin_weight;
 }