public float getDistanceBoneToVertex(IPEBone bone, IPEVertex vertex)
        {
            if (bone.To != -1 && bone.To != 0)
            {
                V3 from = (V3)bone.Position;
                V3 to   = (V3)this.PMD.Bone[bone.To].Position;
                V3 v    = (V3)vertex.Position;

                float d1, d2, d3;
                d1 = (v - from).Length();
                d2 = (v - to).Length();
                V3 line = to - from;
                V3 dif  = v - from;
                if (line.Length() > 0.00001f)
                {
                    d3 = (Cross(line, dif)).Length() / line.Length();
                }
                else
                {
                    d3 = 100000f;
                }

                if (line.Length() > 0)
                {
                    float difDot = Dot(line, dif) / line.Length();
                    //垂線の足がボーン上
                    if (difDot > 0 && difDot < line.Length())
                    {
                        return(Math.Min(d1, Math.Min(d2, d3)));
                    }
                }


                return(Math.Min(d1, d2));
            }
            else
            {
                V3 dif = (V3)((V3)vertex.Position - (V3)bone.Position);
                return(dif.Length());
            }
        }
Exemplo n.º 2
0
        public float getDistanceBoneToVertex(IPEBone bone, IPEVertex vertex)
        {
            if (bone.To != -1 && bone.To != 0)
            {
                V3 from = (V3)bone.Position;
                V3 to = (V3)this.PMD.Bone[bone.To].Position;
                V3 v = (V3)vertex.Position;

                float d1, d2, d3;
                d1 = (v - from).Length();
                d2 = (v - to).Length();
                V3 line = to - from;
                V3 dif = v - from;
                if (line.Length() > 0.00001f)
                {
                    d3 = (Cross(line, dif)).Length() / line.Length();
                }
                else
                {
                    d3 = 100000f;
                }

                if (line.Length() > 0)
                {
                    float difDot = Dot(line, dif) / line.Length();
                    //垂線の足がボーン上
                    if (difDot > 0 && difDot < line.Length())
                    {
                        return Math.Min(d1, Math.Min(d2, d3) );
                    }
                }

                return Math.Min(d1, d2);
            }
            else
            {
                V3 dif = (V3)((V3)vertex.Position - (V3)bone.Position);
                return dif.Length();
            }
        }
        // エントリポイント 
        public override void Run(IPERunArgs args)
        {
            try
            {
                //PMD/PMXファイルを操作するためにおまじない。
                this.host    = args.Host;
                this.builder = this.host.Builder;
                this.bd      = this.host.Builder.SC;
                this.connect = this.host.Connector;
                this.pex     = this.connect.Pmd.GetCurrentStateEx();
                this.PMD     = this.connect.Pmd.GetCurrentState();
                this.PMX     = this.connect.Pmx.GetCurrentState();
                this.Form    = this.connect.Form;
                this.PMDView = this.connect.View.PMDView;


                //-----------------------------------------------------------ここから-----------------------------------------------------------
                //ここから処理開始
                //-----------------------------------------------------------ここから-----------------------------------------------------------


                if (this.connect.Form.PmxFormActivate)
                {
                    for (int i = 0; i < this.PMX.Vertex.Count; i++)
                    {
                        IPXVertex vertex = this.PMX.Vertex[i];
                        V3        vp = (V3)vertex.Position;
                        int       ind1, ind2;
                        ind1 = ind2 = -1;
                        float dis1, dis2;
                        dis1 = dis2 = 10000000;
                        for (int j = 0; j < this.PMX.Bone.Count; j++)
                        {
                            IPXBone bone = this.PMX.Bone[j];
                            V3      bp   = (V3)bone.Position;
                            float   dis;
                            if (bone.ToBone == null)
                            {
                                continue;
                            }
                            else
                            {
                                dis = getDistanceBoneToVertex(bone, vertex);
                            }
                            if (dis < dis1)
                            {
                                dis2 = dis1;
                                ind2 = ind1;
                                ind1 = j;
                                dis1 = dis;
                            }
                            else if (dis < dis2)
                            {
                                dis2 = dis;
                                ind2 = j;
                            }
                        }

                        if (ind1 >= 0)
                        {
                            vertex.Bone1   = this.PMX.Bone[ind1];
                            vertex.Weight1 = 1.0f;
                        }

                        if (ind2 >= 0)
                        {
                            vertex.Bone2 = this.PMX.Bone[ind2];
#if MODE_EXCLUSIVE
                            vertex.Weight2 = 0f;
#else
                            vertex.Weight2 = (1f * dis1 / (dis1 + dis2));
                            vertex.Weight1 = 1.0f - vertex.Weight2;
#endif
                        }
                    }
                }
                else
                {
                    for (int i = 0; i < this.PMD.Vertex.Count; i++)
                    {
                        IPEVertex vertex = this.PMD.Vertex[i];
                        V3        vp = (V3)vertex.Position;
                        int       ind1, ind2;
                        ind1 = ind2 = -1;
                        float dis1, dis2;
                        dis1 = dis2 = 10000000;
                        for (int j = 0; j < this.PMD.Bone.Count; j++)
                        {
                            IPEBone bone = this.PMD.Bone[j];
                            V3      bp   = (V3)bone.Position;
                            float   dis;
                            if (bone.To == -1 || bone.To == 0)
                            {
                                continue;
                            }
                            else
                            {
                                dis = getDistanceBoneToVertex(bone, vertex);
                            }
                            //                        float dis = (bp - vp).Length();
                            if (dis < dis1)
                            {
                                dis2 = dis1;
                                ind2 = ind1;
                                ind1 = j;
                                dis1 = dis;
                            }
                            else if (dis < dis2)
                            {
                                dis2 = dis;
                                ind2 = j;
                            }
                        }

                        if (ind1 >= 0)
                        {
                            vertex.Bone1 = ind1;
                        }
                        if (ind2 >= 0)
                        {
                            vertex.Bone2 = ind2;
#if MODE_EXCLUSIVE
                            vertex.Weight = 100;
#else
                            vertex.Weight = (int)(100f * dis2 / (dis1 + dis2));
#endif
                        }
                    }
                }


                //-----------------------------------------------------------ここまで-----------------------------------------------------------
                //処理ここまで
                //-----------------------------------------------------------ここまで-----------------------------------------------------------
                //モデル・画面を更新します。
                this.Update();
#if MODE_EXCLUSIVE
                MessageBox.Show(this.PMD.Vertex.Count.ToString() + "個の頂点のウェイトを最短排他形式で設定しました。",
                                "ウェイト自動設定(排他的)", MessageBoxButtons.OK, MessageBoxIcon.Information);
#else
                MessageBox.Show(this.PMX.Vertex.Count.ToString() + "個の頂点のウェイトを中間補完形式で設定しました。",
                                "ウェイト自動設定(補完的)", MessageBoxButtons.OK, MessageBoxIcon.Information);
#endif
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "エラー", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }
        }