Example #1
0
        public static int FindUsingBone(IPXBone b, IPXVertex v)
        {
            if (v.Bone1.Equals(b))
            {
                return(0);
            }

            if (v.Bone2 == null)
            {
                return(-1);
            }
            if (v.Bone2.Equals(b))
            {
                return(1);
            }

            if (v.Bone3 == null)
            {
                return(-1);
            }
            if (v.Bone3.Equals(b))
            {
                return(2);
            }

            if (v.Bone4 == null)
            {
                return(-1);
            }
            if (v.Bone4.Equals(b))
            {
                return(3);
            }
            return(-1);
        }
Example #2
0
        private static void writeBoneNode(
            Node node, NodeInfo info, StreamWriter writer)
        {
            IPXBone bone  = (IPXBone)node.pmxElement;
            string  shape = NodeConfig.determineShape(info);
            string  color = NodeConfig.determineColor(info);
            string  style = NodeConfig.determineStyle(info);

            int    index     = boneIndexDict[bone];
            string nodeLabel = string.Format("{0:D}: {1}", index, bone.Name);
            string bodyLabel = null;

            if (info.hasAttr("物理演算"))
            {
                bodyLabel = info.getAttr("物理演算");
            }
            else if (info.hasAttr("ボーン追従"))
            {
                bodyLabel = info.getAttr("ボーン追従");
            }
            string label = null == bodyLabel ?
                           "\"" + nodeLabel + "\"":
                           "\"" + nodeLabel + "\\n(" + bodyLabel + ")\"";

            writer.WriteLine(string.Format(
                                 "{0} [shape={1}, label={2}, style =\"{3}\"," +
                                 "fillcolor=\"{4}\"];",
                                 node.id, shape, label, style, color));
        }
Example #3
0
        private static Node makeBoneNode(IPXBone bone)
        {
            int    index  = boneIndexDict[bone];
            string boneID = "BONE_" + index.ToString();

            return(new Node(boneID, bone));
        }
Example #4
0
 // ボーン(ノード)の属性を設定する
 private static void updateNodeAttrs(BoneGraph g)
 {
     foreach (Node node in g.nodes)
     {
         NodeInfo info = g.directedEdges[node].Item1;
         IPXBone  bone = (IPXBone)node.pmxElement;
         if (bone.IsIK)
         {
             info.setAttr("IKボーン", "");
         }
         if (bone.Controllable)
         {
             info.setAttr("操作可能", "");
         }
         else
         {
             info.setAttr("操作不可能", "");
         }
         if (bone.Visible)
         {
             info.setAttr("表示", "");
         }
         else
         {
             info.setAttr("非表示", "");
         }
         if (bone2bodies.ContainsKey(bone))
         {
             string bodytext = "";
             bool   first    = true;
             bool   dyn      = false;
             foreach (IPXBody body in bone2bodies[bone])
             {
                 int bodyIndex = bodyIndexDict[body];
                 if (!first)
                 {
                     bodytext += ", ";
                 }
                 bodytext +=
                     String.Format("{0:D}: {1}", bodyIndex, body.Name);
                 if (BodyMode.Dynamic == body.Mode ||
                     BodyMode.DynamicWithBone == body.Mode)
                 {
                     dyn = true;
                 }
                 first = false;
             }
             if (dyn)
             {
                 info.setAttr("物理演算", bodytext);
             }
             else
             {
                 info.setAttr("ボーン追従", bodytext);
             }
         }
     }
 }
Example #5
0
        private float DistortedDist(IPXBone bone, IPXVertex vertex)
        {
            var dist = BoneLocalVerticePosition(bone, vertex);

            dist.X *= space.X;
            dist.Y *= space.Y;
            dist.Z *= space.Z;
            return(dist.Length());
        }
Example #6
0
 private void TestMoveVertice(IPXBone selBone)
 {
     for (int v = 0; v < Pmx.Vertex.Count; v++)
     {
         var     item    = Pmx.Vertex[v];
         Vector3 vector3 = BoneLocalVerticePosition(selBone, item);
         item.Position = vector3;
     }
 }
Example #7
0
        private static BoneGraph makeBoneGraph(IPXPmx pmx)
        {
            BoneGraph boneGraph = new BoneGraph();

            foreach (IPXBone bone in pmx.Bone)
            {
                Node boneNode = makeBoneNode(bone);
                ///////////
                // 4 種類のエッジを作成する
                // (1) 親 -> 子 (type=親子)
                // (2) 付与親 -> 子 (type=付与親)
                // (2) IKボーン -> IKターゲットボーン (type=IKターゲット)
                // (3) IKボーン -> IKリンクボーン (type=IKリンク)

                boneGraph.addNode(boneNode); // 4種に当てはまらないボーン用

                // (1)
                IPXBone parentBone = bone.Parent;
                if (null != parentBone)
                {
                    Node     parentNode = makeBoneNode(parentBone);
                    EdgeInfo info       = new EdgeInfo(boneNode, "親子");
                    boneGraph.addEdge(parentNode, info);
                }
                // (2)
                if (null != bone.AppendParent &&
                    (bone.IsAppendRotation || bone.IsAppendTranslation))
                {
                    Node     appendNode = makeBoneNode(bone.AppendParent);
                    EdgeInfo info       = new EdgeInfo(boneNode, "付与親");
                    info.setAttr(
                        "weight",
                        string.Format("{0:F3}", bone.AppendRatio));
                    boneGraph.addEdge(appendNode, info);
                }
                // (3), (4)
                if (bone.IsIK && null != bone.IK)
                {
                    if (null != bone.IK.Target)
                    {
                        Node     targetNode = makeBoneNode(bone.IK.Target);
                        EdgeInfo targetInfo = new EdgeInfo(
                            targetNode, "IKターゲット");
                        boneGraph.addEdge(boneNode, targetInfo);
                    }
                    foreach (IPXIKLink ikLink in bone.IK.Links)
                    {
                        Node     linkNode = makeBoneNode(ikLink.Bone);
                        EdgeInfo linkInfo = new EdgeInfo(
                            linkNode, "IKリンク");
                        boneGraph.addEdge(boneNode, linkInfo);
                    }
                }
            }
            return(boneGraph);
        }
Example #8
0
 public static void SetTargetPosition(IPXBone bone, V3 pos)
 {
     if (bone.ToBone != null)
     {
         bone.ToBone.Position = pos;
     }
     else
     {
         bone.ToOffset = pos - bone.Position;
     }
 }
Example #9
0
 private IEnumerable <int> VertexIndiceInRange(IPXBone selBone, float range)
 {
     for (int v = 0; v < Pmx.Vertex.Count; v++)
     {
         var     item    = Pmx.Vertex[v];
         Vector3 vector3 = BoneLocalVerticePosition(selBone, item);
         vector3.Z *= 0.2f;
         if (vector3.Length() < range)
         {
             yield return(v);
         }
     }
 }
Example #10
0
        //public static V3

        public static V3 TargetPosition(IPXBone bone)
        {
            var worldBoneTarget = new V3();

            if (bone.ToBone != null)
            {
                worldBoneTarget = bone.ToBone.Position;
            }
            else
            {
                worldBoneTarget = bone.Position + bone.ToOffset;
            }

            return(worldBoneTarget);
        }
Example #11
0
        private Vector3 BoneLocalVerticePosition(IPXBone selBone, IPXVertex item)
        {
            var pos = PmxUtil.BoneAttitude(selBone);

            pos.Decompose(out Vector3 scale, out Quaternion rot, out Vector3 loc);
            rot = Quaternion.Invert(rot);
            //foreach (var item in Pmx.Vertex)
            {
                // なんかpositionなくなる
                //item.Position -= selBone.Position;
                //Vector4 vector4 = Vector3.Transform(item.Position, Matrix.RotationAxis(rot.Axis, rot.Angle));
                //item.Position = new V3(vector4.X, vector4.Y, vector4.Z);
                var     tmp     = item.Position - selBone.Position;
                Vector4 vector4 = Vector3.Transform(tmp, Matrix.RotationAxis(rot.Axis, rot.Angle));
                return(new V3(vector4.X, vector4.Y, vector4.Z));
            }
        }
Example #12
0
        public void Do()
        {
            foreach (var bone in Bones)
            {
                IPXBone createdBone = bone.Clone() as IPXBone;

                bone.Name  += "R";
                bone.NameE += "R";

                bone.AppendParent        = createdBone;
                bone.AppendRatio         = 1;
                bone.IsAppendLocal       = false;
                bone.IsAppendRotation    = true;
                bone.IsAppendTranslation = true;

                Pmx.Bone.Insert(Pmx.Bone.IndexOf(bone), createdBone);
            }
        }
Example #13
0
        public static Matrix BoneAttitude(IPXBone bone)
        {
            V3  worldBoneTarget = TargetPosition(bone);
            var toward          = worldBoneTarget - bone.Position;

            toward.Normalize();
            var up = Vector3.UnitY;

            if (Vector3.Dot(up, toward) > 0.8)
            {
                up = Vector3.UnitX;
            }

            //Matrix right = Matrix.LookAtRH(bone.Position, worldBoneTarget, up);
            Matrix right = LookAt(bone.Position, worldBoneTarget, up);

            right.Decompose(out Vector3 scale, out Quaternion rot, out Vector3 loc);
            return(Matrix.Translation(bone.Position) * right);
        }
Example #14
0
        // Generate straight bone chain
        public static IPXBone[] GenerateChain(IPXPmxBuilder builder, int count, Vector3 distance, Vector3 center, string name, string nameE)
        {
            IPXBone[] bones = new IPXBone[count];

            for (int i = 0; i < count; ++i)
            {
                IPXBone bone = builder.Bone();
                bone.Name     = name.Replace("#", i.ToString()).Replace("&", (i + 1).ToString());
                bone.NameE    = nameE.Replace("#", i.ToString()).Replace("&", (i + 1).ToString());
                bone.Position = center + (distance * i);
                if (i > 0)
                {
                    bone.Parent        = bones[i - 1];
                    bone.Parent.ToBone = bone;
                }
                bones[i] = bone;
            }

            return(bones);
        }
        public float getDistanceBoneToVertex(IPXBone bone, IPXVertex vertex)
        {
            if (bone.ToBone != null)
            {
                V3 from = (V3)bone.Position;
                V3 to   = (V3)bone.ToBone.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());
            }
        }
Example #16
0
        public float getDistanceBoneToVertex(IPXBone bone, IPXVertex vertex)
        {
            if (bone.ToBone != null)
            {
                V3 from = (V3)bone.Position;
                V3 to = (V3)bone.ToBone.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();
            }
        }
Example #17
0
        public static float BoneWeight(IPXBone b, IPXVertex v)
        {
            int usingBone = FindUsingBone(b, v);

            if (usingBone == 0)
            {
                return(v.Weight1);
            }
            if (usingBone == 1)
            {
                return(v.Weight2);
            }
            if (usingBone == 2)
            {
                return(v.Weight3);
            }
            if (usingBone == 3)
            {
                return(v.Weight4);
            }
            return(0);
        }
Example #18
0
        // Create segmented bone chain
        public static IPXBone[] GenerateSegmentedChain(IPXPmxBuilder builder, int count, Vector3[] points, string name, string nameE)
        {
            IPXBone[] bones        = new IPXBone[count];
            int       segmentCount = points.Length - 1;
            float     totalLength  = 0;

            float[] segmentLengths = new float[segmentCount];

            // Determine the lengths of segments
            for (int i = 0; i < segmentCount; ++i)
            {
                float length = points[i].Distance(points[i + 1]);
                segmentLengths[i] = length;
                totalLength      += length;
            }

            // Determine the number of links that can fit into each segment
            float avgDist = totalLength / count;

            int[] bonesPerSegment = new int[segmentCount];
            int   remaining       = count;

            for (int i = 0; i < segmentCount - 1; ++i)
            {
                bonesPerSegment[i] = Mathf.RoundToInt(segmentLengths[i] / avgDist);
                remaining         -= bonesPerSegment[i];
            }
            // Put any remaining bones into the last segment
            bonesPerSegment[segmentCount - 1] = remaining;

            // Create the bones
            for (int i = 0; i < segmentCount; ++i)
            {
                System.Windows.Forms.MessageBox.Show($"{i}\t{segmentLengths[i]}");
            }

            return(bones);
        }
Example #19
0
        private void buttonRun_Click(object sender, EventArgs e)
        {
            var selectedMaterialID = listBoxMaterial.SelectedIndex - 1;

            if (selectedMaterialID < 0)
            {
                MessageBox.Show("ウェイト転写対象の材質を選択してください。");
                return;
            }
            if (comboBoxBone.SelectedIndex < 0)
            {
                MessageBox.Show("ウェイト対象のボーンを選択してください。");
                return;
            }

            pmx = args.Host.Connector.Pmx.GetCurrentState();
            IPXMaterial targetMaterial = pmx.Material[selectedMaterialID];
            IPXBone     targetBone     = pmx.Bone[comboBoxBone.SelectedIndex];

            var mesh = new PXMesh(targetMaterial);

            for (int i = 0; i < mesh.Vertices.Count; i++)
            {
                IPXVertex v = mesh.Vertices[i];
                (IPXBone bone, float weight)bw = (targetBone, GetPointColor(v).R / 255f);
                var vertexWB = Utility.GetWeights(v);

                //頂点のウェイトを編集
                vertexWB.RemoveAll(w => w.bone == bw.bone);
                Utility.NormalizeWeights(vertexWB, 1 - bw.weight);
                vertexWB.Add(bw);
                Utility.SetVertexWeights(vertexWB, ref v);
            }

            Utility.Update(args.Host.Connector, pmx, PmxUpdateObject.Vertex);
            MessageBox.Show("完了");
        }
Example #20
0
        // Create uneven bone chain along spline
        public static IPXBone[] GenerateSplineChain(IPXPmxBuilder builder, int count, Vector3[] points, string name, string nameE)
        {
            IPXBone[] bones = new IPXBone[count];

            // Construct a cubic Bézier curve from the points
            // Place a link at every t = (1 / count) point
            float dt = 1.0f / count;

            for (int i = 0; i < count; ++i)
            {
                IPXBone bone = builder.Bone();
                bone.Name     = name.Replace("#", i.ToString()).Replace("&", (i + 1).ToString());
                bone.NameE    = nameE.Replace("#", i.ToString()).Replace("&", (i + 1).ToString());
                bone.Position = Mathf.Curve.BezierPoint(dt * i, points);
                if (i > 0)
                {
                    bone.Parent        = bones[i - 1];
                    bone.Parent.ToBone = bone;
                }
                bones[i] = bone;
            }

            return(bones);
        }
Example #21
0
 //---------------------------------------------------------------------
 // IK関連
 //---------------------------------------------------------------------
 // targetBone(制限角low~high)のIKLinkを作成
 public IPXIKLink MakeIKLink(IPXBone targetBone, V3 low, V3 high)
 {
     return targetBone == null ? null : bdx.IKLink(targetBone, low, high);
 }
Example #22
0
        private void generateButton_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(namingText.Text))
            {
                MessageBox.Show("The name cannot be empty!");
                return;
            }
            switch (positionSelect.SelectedIndex)
            {
            case 0:
                if (lastPointVector.Value.Magnitude <= 0)
                {
                    MessageBox.Show("The target vector cannot be zero!");
                    return;
                }
                break;

            case 1:
                if (linkNumber.Value < pointCount.Value)
                {
                    MessageBox.Show("The number of links must not be less than the number of control points.");
                    return;
                }
                break;

            default:
                break;
            }

            if (editPoints.Checked)
            {
                editPoints.Checked = false;
            }

            IPXPmx  pmx    = _args.Host.Connector.Pmx.GetCurrentState();
            IPXBone parent = null;

            if (parentBoneSelect.SelectedIndex > 0)
            {
                parent = pmx.Bone[parentBoneSelect.SelectedIndex - 1];
            }
            IPXBone[] chain = null;

            int     count;
            Vector3 start;
            Vector3 delta;

            switch (positionSelect.SelectedIndex)
            {
            case 0:     // From start through target

                start = firstPointVector.Value;
                delta = lastPointVector.Value.Normalized * (float)distanceNumber.Value;
                count = (int)Math.Round(linkNumber.Value);
                chain = Builder.GenerateChain(_args.Host.Builder.Pmx, Math.Max(count, 1), delta, start, namingText.Text, namingEnText.Text);
                break;

            case 1:     // Segmented path
                count = (int)Math.Round(linkNumber.Value);
                chain = Builder.GenerateSegmentedChain(_args.Host.Builder.Pmx, count, _curvePoints, namingText.Text, namingEnText.Text);
                break;

            case 2:     // Along a spline
                count = (int)Math.Round(linkNumber.Value);
                chain = Builder.GenerateSplineChain(_args.Host.Builder.Pmx, count, _curvePoints, namingText.Text, namingEnText.Text);
                break;

            case 3:     // Along a spline with even distribution
                count = (int)Math.Round(linkNumber.Value);
                chain = Builder.GenerateSplineChainEvenSpaced(_args.Host.Builder.Pmx, count, _curvePoints, namingText.Text, namingEnText.Text);
                break;

            default:
                break;
            }

            if (chainTypeIK.Checked)
            {
                IPXBone handle = _args.Host.Builder.Pmx.Bone();
                handle.Parent        = parent;
                handle.Name          = namingText.Text.Replace("#", "IK").Replace("&", "IK");
                handle.NameE         = namingEnText.Text.Replace("#", "IK").Replace("&", "IK");
                handle.IsTranslation = true;
                handle.IsIK          = true;
                IPXIK ik = handle.IK;

                for (int i = chain.Length - 2; i >= 0; --i)
                {
                    ik.Links.Add(_args.Host.Builder.Pmx.IKLink(chain[i]));
                }

                ik.Target       = chain[chain.Length - 1];
                ik.Angle        = (float)((20.0 / 180.0) * Math.PI);
                ik.LoopCount    = 10;
                handle.Position = ik.Target.Position;

                pmx.Bone.Add(handle);
            }

            if (createPhysics.Checked)
            {
                IPXJoint pj = null;
                if (_physicsSettings.AttachToParent)
                {
                    IPXBody pb = pmx.Body.Where(b => b.Bone == parent).FirstOrDefault();
                    if (pb == null)
                    {
                        MessageBox.Show("Could not attach physics chain to the parent bone because it doesn't have a rigidbody.", "Warning");
                    }
                    else
                    {
                        pj          = _args.Host.Builder.Pmx.Joint();
                        pj.Name     = namingText.Text.Replace("#", "P").Replace("&", "P");
                        pj.NameE    = namingEnText.Text.Replace("#", "P").Replace("&", "P");
                        pj.Position = pb.Bone.Position;
                        pj.BodyA    = pb;
                        pmx.Joint.Add(pj);
                    }
                }
                Builder.GeneratePhysics(_args.Host.Builder.Pmx, chain, _physicsSettings, out IPXBody[] rigidbodies, out IPXJoint[] joints);
Example #23
0
 // 選択されたボーン配列を取得
 public IPXBone[] SelectedBones()
 {
     var bi = connect.View.PmxView.GetSelectedBoneIndices();
     if (bi.Length == 0) return null;
     var ret = new IPXBone[bi.Length];
     for (var i = 0; i < bi.Length; i++) ret[i] = bone[bi[i]];
     return ret;
 }
Example #24
0
 // 新しい名前でボーンを複製
 public IPXBone CloneBone(IPXBone origBone, string newName)
 {
     var bx = (IPXBone)origBone.Clone();
     bx.Name = newName;
     return bx;
 }
Example #25
0
 // ボーンを表示枠に追加
 public void AddBoneToNode(IPXNode targetNode, IPXBone targetBone)
 {
     targetNode.Items.Add(bdx.BoneNodeItem(targetBone));
 }
Example #26
0
 // targetBoneの直前にnewBoneを挿入
 // 返り値は挿入できたかどうか
 public bool InsertBoneBefore(IPXBone targetBone, IPXBone newBone)
 {
     for (var i = 0; i < bone.Count; i++)
     {
         if (bone[i] != targetBone) continue;
         bone.Insert(i, newBone);
         return true;
     }
     return false;
 }
Example #27
0
 public bool InsertBoneBefore(string targetBoneName, IPXBone newBone)
 {
     var targetBone = FindBone(targetBoneName);
     if (targetBone == null) return false;
     return InsertBoneBefore(targetBone, newBone);
 }
Example #28
0
 // ボーンを表示枠から削除
 public void RemoveBoneFromNode(IPXNode targetNode, IPXBone targetBone)
 {
     var b = targetNode.Items.FirstOrDefault(ni => ni.IsBone && ni.BoneItem.Bone == targetBone);
     if (b == null) return;
     targetNode.Items.Remove(b);
 }
Example #29
0
 // targetBoneにlinkBoneを回転付与親として設定
 public bool AppendRotation(IPXBone targetBone, IPXBone linkBone, float ratio)
 {
     if (targetBone == null || linkBone == null) return false;
     targetBone.IsAppendRotation = true;
     targetBone.AppendParent = linkBone;
     targetBone.AppendRatio = ratio;
     return true;
 }
Example #30
0
 public IPXIKLink IKLink(IPXBone bone, V3 low, V3 high)
 {
     throw new NotImplementedException();
 }
Example #31
0
 public IPXBoneNodeItem BoneNodeItem(IPXBone bone)
 {
     throw new NotImplementedException();
 }
Example #32
0
 // targetBoneのIKLinkを作成
 public IPXIKLink MakeIKLink(IPXBone targetBone)
 {
     return targetBone == null ? null : bdx.IKLink(targetBone);
 }
Example #33
0
        private void ButtonExecute_Click(object sender, EventArgs e)
        {
            IPXPmx pmx = args.Host.Builder.Pmx.Pmx();

            pmx.ModelInfo.ModelName = textBoxModelName.Text;
            pmx.ModelInfo.Comment   = textBoxModelText.Text;

            // 作成したpmxにマテリアルをコピー
            foreach (int i in listBoxMaterial.SelectedIndices)
            {
                pmx.Material.Add(currentPmx.Material[i]);
            }

            // マテリアルに含まれる頂点のリストを作成
            List <IPXVertex> vertices = new List <IPXVertex>();

            foreach (var m in pmx.Material)
            {
                foreach (var f in m.Faces)
                {
                    vertices.Add(f.Vertex1);
                    vertices.Add(f.Vertex2);
                    vertices.Add(f.Vertex3);
                }
            }
            // 重複を除去
            vertices = vertices.Distinct().ToList();
            foreach (var v in vertices)
            {
                pmx.Vertex.Add(v);
            }

            // 頂点のウェイトに基づいてボーンをコピー
            if (checkBoxBone.Checked)
            {
                if (radioAllBone.Checked)
                {
                    foreach (var b in currentPmx.Bone)
                    {
                        pmx.Bone.Add(b);
                    }
                    if (checkBoxPhysics.Checked)
                    {
                        foreach (var b in currentPmx.Body)
                        {
                            pmx.Body.Add(b);
                        }
                        foreach (var j in currentPmx.Joint)
                        {
                            pmx.Joint.Add(j);
                        }
                    }
                }
                else
                {
                    // 元のボーン順を保存
                    Dictionary <IPXBone, int> boneIndex = new Dictionary <IPXBone, int>();
                    for (int i = 0; i < currentPmx.Bone.Count; i++)
                    {
                        boneIndex.Add(currentPmx.Bone[i], i);
                    }

                    // 関連ボーン
                    List <IPXBone> bones = new List <IPXBone>();
                    foreach (var v in vertices)
                    {
                        if (v.Bone1 != null)
                        {
                            bones.Add(v.Bone1);
                        }
                        if (v.Bone2 != null)
                        {
                            bones.Add(v.Bone2);
                        }
                        if (v.Bone3 != null)
                        {
                            bones.Add(v.Bone3);
                        }
                        if (v.Bone4 != null)
                        {
                            bones.Add(v.Bone4);
                        }
                    }
                    bones = bones.Distinct().ToList();


                    if (checkBoxPhysics.Checked)
                    {
                        // 関連ボーンの関連剛体
                        List <IPXBody> bodies = new List <IPXBody>();
                        foreach (var b in bones)
                        {
                            bodies.AddRange(currentPmx.Body.Where(x => x.Bone == b));
                        }
                        bodies = bodies.Distinct().ToList();
                        // 関連剛体の関連ジョイント
                        List <IPXJoint> joints = new List <IPXJoint>();
                        foreach (var b in bodies)
                        {
                            joints.AddRange(currentPmx.Joint.Where(x => x.BodyA == b || x.BodyB == b));
                        }
                        joints = joints.Distinct().ToList();
                        // ジョイントに必要な剛体がbodiesに不足していた場合追加
                        foreach (var j in joints)
                        {
                            if (!bodies.Any(b => b == j.BodyA))
                            {
                                bodies.Add(j.BodyA);
                            }
                            if (!bodies.Any(b => b == j.BodyB))
                            {
                                bodies.Add(j.BodyB);
                            }
                        }
                        // 剛体に必要なボーンがbonesに不足していた場合追加
                        foreach (var b in bodies)
                        {
                            if (!bones.Any(x => x == b.Bone))
                            {
                                bones.Add(b.Bone);
                            }
                        }

                        // 剛体・ジョイントの並び順を戻す
                        Dictionary <IPXBody, int> bodyIndex = new Dictionary <IPXBody, int>();
                        for (int i = 0; i < currentPmx.Body.Count; i++)
                        {
                            bodyIndex.Add(currentPmx.Body[i], i);
                        }
                        Dictionary <IPXJoint, int> jointIndex = new Dictionary <IPXJoint, int>();
                        for (int i = 0; i < currentPmx.Joint.Count; i++)
                        {
                            jointIndex.Add(currentPmx.Joint[i], i);
                        }

                        bodies.Sort((a, b) => bodyIndex[a] - bodyIndex[b]);
                        joints.Sort((a, b) => jointIndex[a] - jointIndex[b]);

                        foreach (var b in bodies)
                        {
                            pmx.Body.Add(b);
                        }
                        foreach (var j in joints)
                        {
                            pmx.Joint.Add(j);
                        }
                    }

                    bones.Sort((a, b) => boneIndex[a] - boneIndex[b]);

                    if (radioRelationBone.Checked)
                    {
                        foreach (var b in bones)
                        {
                            pmx.Bone.Add(b);
                        }
                    }

                    if (radioRelationBoneAndParent.Checked)
                    {
                        List <IPXBone> bonesWithParent = new List <IPXBone>();
                        //関連ボーンの親を遡って保持
                        for (int i = 0; i < bones.Count; i++)
                        {
                            IPXBone b      = bones[i];
                            IPXBone forcus = b;
                            while (forcus != null)
                            {
                                if (bonesWithParent.Exists(x => x == forcus))
                                {
                                    break;
                                }
                                bonesWithParent.Add(forcus);
                                if (forcus.AppendParent != null && !bones.Exists(x => x == forcus.AppendParent))
                                {
                                    bones.Add(forcus.AppendParent);
                                }
                                forcus = forcus.Parent;
                            }
                        }

                        bonesWithParent.Sort((a, b) => boneIndex[a] - boneIndex[b]);
                        foreach (var b in bonesWithParent)
                        {
                            pmx.Bone.Add(b);
                        }
                    }
                }
            }

            // モーフをコピー
            if (checkBoxMorph.Checked)
            {
                foreach (var m in currentPmx.Morph)
                {
                    IPXMorph morph       = m;
                    bool     morphExists = true;
                    switch (m.Kind)
                    {
                    case MorphKind.Vertex:
                        List <IPXVertexMorphOffset> vmo = m.Offsets.ToList().ConvertAll(o => (IPXVertexMorphOffset)o);
                        foreach (var o in vmo)
                        {
                            if (!vertices.Exists(v => v == o.Vertex))
                            {
                                morph.Offsets.Remove(o);
                            }
                        }
                        break;

                    case MorphKind.UV:
                    case MorphKind.UVA1:
                    case MorphKind.UVA2:
                    case MorphKind.UVA3:
                    case MorphKind.UVA4:
                        List <IPXUVMorphOffset> umo = m.Offsets.ToList().ConvertAll(o => (IPXUVMorphOffset)o);
                        foreach (var o in umo)
                        {
                            if (!vertices.Exists(v => v == o.Vertex))
                            {
                                morph.Offsets.Remove(o);
                            }
                        }
                        break;

                    case MorphKind.Material:
                        List <IPXMaterialMorphOffset> mmo = m.Offsets.ToList().ConvertAll(o => (IPXMaterialMorphOffset)o);
                        foreach (var o in mmo)
                        {
                            if (!pmx.Material.Contains(o.Material))
                            {
                                morph.Offsets.Remove(o);
                            }
                        }
                        break;

                    default:
                        morphExists = false;
                        break;
                    }
                    if (morphExists && morph.Offsets.Count != 0)
                    {
                        pmx.Morph.Add(morph);
                    }
                }
            }

            Update(args.Host.Connector, pmx, PmxUpdateObject.All);
            MessageBox.Show("完了");
            Reload();
        }
Example #34
0
        /// <summary>
        /// Parses the Wavefront Object file at the provided path and returns the operation's result.
        /// </summary>
        public static ImportResult Import(string path, IPXPmxBuilder builder, ImportSettings settings, IOProgress progress)
        {
            // Cancel the process if needed
            if (progress.CancellationToken.IsCancellationRequested)
            {
                progress.CancellationToken.ThrowIfCancellationRequested();
            }

            IPXPmx pmx = builder.Pmx();

            pmx.Clear();
            pmx.ModelInfo.ModelName = pmx.ModelInfo.ModelNameE = Path.GetFileNameWithoutExtension(path);
            pmx.ModelInfo.Comment   = pmx.ModelInfo.CommentE = "(Imported from OBJ by WPlugins.ObjIO)";
            StreamReader reader = null;

            System.Globalization.NumberFormatInfo fi = System.Globalization.NumberFormatInfo.InvariantInfo;
            System.Globalization.NumberStyles     ns = System.Globalization.NumberStyles.Float;

            // Model elements
            List <V3> vList  = new List <V3>();
            List <V2> vtList = new List <V2>();
            List <V3> vnList = new List <V3>();
            Dictionary <Tuple <int, int, int>, int> vertexDictionary = new Dictionary <Tuple <int, int, int>, int>();
            Dictionary <string, IPXMaterial>        materials        = new Dictionary <string, IPXMaterial>();
            IPXMaterial currentMaterial = null;

            // Values derived from settings
            V3 positionScale = new V3(settings.ScaleX, settings.ScaleY, settings.ScaleZ) * (settings.UseMetricUnits ? 0.254f : 0.1f);

            // Statistics
            int lineNumber = 0;

            try
            {
                reader = new StreamReader(path);
                char[] separator = { ' ' };
                while (!reader.EndOfStream)
                {
                    System.Threading.Thread.Sleep(2);

                    // Cancel the process if needed
                    if (progress.CancellationToken.IsCancellationRequested)
                    {
                        progress.CancellationToken.ThrowIfCancellationRequested();
                    }

                    string line = reader.ReadLine().Trim();
                    ++lineNumber;
                    ++progress.LineNumber;
                    progress.Report(IOProgress.Percent(reader.BaseStream.Position, reader.BaseStream.Length));

                    // Skip empty lines and comments
                    if (string.IsNullOrWhiteSpace(line) || line[0] == '#')
                    {
                        continue;
                    }

                    string[] split = line.Split(separator, StringSplitOptions.RemoveEmptyEntries);
                    switch (split[0])
                    {
                    // Vertex position
                    case "v":
                        try
                        {
                            float x = float.Parse(split[1], ns, fi);
                            float y = float.Parse(split[2], ns, fi);
                            float z = float.Parse(split[3], ns, fi);
                            vList.Add(new V3(x, y, -z));
                        }
                        catch (FormatException ex)
                        {
                            if (progress.ReportError(string.Format("A format exception has occured: {0}", line)))
                            {
                                return(ImportResult.Fail(ex, progress.WarningCount, progress.ErrorCount));
                            }
                            vList.Add(new V3());
                        }
                        break;

                    // Vertex texture coordinates
                    case "vt":
                        try
                        {
                            // Technically this can be a V3 or any vector, but PMX only uses the first two elements for the main UV channel.
                            float x = float.Parse(split[1], ns, fi);
                            float y = float.Parse(split[2], ns, fi);
                            vtList.Add(new V2(x, -y));
                        }
                        catch (FormatException ex)
                        {
                            if (progress.ReportError(string.Format("A format exception has occured: {0}", line)))
                            {
                                return(ImportResult.Fail(ex, progress.WarningCount, progress.ErrorCount));
                            }
                            vtList.Add(new V2());
                        }
                        break;

                    // Vertex normal
                    case "vn":
                        try
                        {
                            float x = float.Parse(split[1], ns, fi);
                            float y = float.Parse(split[2], ns, fi);
                            float z = float.Parse(split[3], ns, fi);
                            vnList.Add(new V3(x, y, -z));
                        }
                        catch (FormatException ex)
                        {
                            if (progress.ReportError(string.Format("A format exception has occured: {0}", line)))
                            {
                                return(ImportResult.Fail(ex, progress.WarningCount, progress.ErrorCount));
                            }
                            vnList.Add(new V3());
                        }
                        break;

                    // Face definition
                    case "f":
                        if (currentMaterial == null)
                        {
                            progress.ReportWarning(string.Format("Encountered a face record when no active group was set.", lineNumber));
                            currentMaterial = builder.Material();
                        }

                        // Triangle
                        if (split.Length == 4)
                        {
                            int  v  = 0;
                            int  vt = 0;
                            int  vn = 0;
                            bool newVertex;

                            try
                            {
                                // Split each vertex assignment triple into its respective v/vt/vn indices.
                                GetVertexElements(split[1], out v, out vt, out vn);
                                // Based on the indices, determine if the vertex assignment is unique or already exists. A vertex is considered unique if one or more index is different, regardless of the vectors they represent.
                                newVertex = GetUniqueVertex(v, vt, vn, vertexDictionary, pmx.Vertex.Count, out int index1);
                                if (newVertex)
                                {
                                    IPXVertex vert = builder.Vertex();
                                    pmx.Vertex.Add(vert);       // The new vertex is added to the end of the list, making its index equal to the list's count before the addition.
                                    if (v >= 0)
                                    {
                                        vert.Position = vList[v] * positionScale;
                                    }
                                    if (vt >= 0)
                                    {
                                        vert.UV = vtList[vt];
                                    }
                                    if (vn >= 0)
                                    {
                                        vert.Normal = vnList[vn];
                                    }
                                }
                                IPXVertex vertex1 = pmx.Vertex[index1];

                                // Repeat the same process for the rest of the vertex triples.
                                GetVertexElements(split[2], out v, out vt, out vn);
                                newVertex = GetUniqueVertex(v, vt, vn, vertexDictionary, pmx.Vertex.Count, out int index2);
                                if (newVertex)
                                {
                                    IPXVertex vert = builder.Vertex();
                                    pmx.Vertex.Add(vert);
                                    if (v >= 0)
                                    {
                                        vert.Position = vList[v] * positionScale;
                                    }
                                    if (vt >= 0)
                                    {
                                        vert.UV = vtList[vt];
                                    }
                                    if (vn >= 0)
                                    {
                                        vert.Normal = vnList[vn];
                                    }
                                }
                                IPXVertex vertex2 = pmx.Vertex[index2];

                                GetVertexElements(split[3], out v, out vt, out vn);
                                newVertex = GetUniqueVertex(v, vt, vn, vertexDictionary, pmx.Vertex.Count, out int index3);
                                if (newVertex)
                                {
                                    IPXVertex vert = builder.Vertex();
                                    pmx.Vertex.Add(vert);
                                    if (v >= 0)
                                    {
                                        vert.Position = vList[v] * positionScale;
                                    }
                                    if (vt >= 0)
                                    {
                                        vert.UV = vtList[vt];
                                    }
                                    if (vn >= 0)
                                    {
                                        vert.Normal = vnList[vn];
                                    }
                                }
                                IPXVertex vertex3 = pmx.Vertex[index3];

                                // Build the triangle and assign the vertices; use reverse order and negative normal vectors if the triangles are reversed.
                                IPXFace face = builder.Face();
                                if (settings.FlipFaces)
                                {
                                    vertex1.Normal *= -1;
                                    vertex2.Normal *= -1;
                                    vertex3.Normal *= -1;
                                    face.Vertex1    = vertex1;
                                    face.Vertex2    = vertex2;
                                    face.Vertex3    = vertex3;
                                }
                                else
                                {
                                    face.Vertex1 = vertex3;
                                    face.Vertex2 = vertex2;
                                    face.Vertex3 = vertex1;
                                }
                                currentMaterial.Faces.Add(face);
                            }
                            catch (Exception ex)
                            {
                                if (progress.ReportError(ex.ToString()))
                                {
                                    return(ImportResult.Fail(ex, progress.WarningCount, progress.ErrorCount));
                                }
                            }
                        }
                        // Quad
                        else if (split.Length == 5)
                        {
                            int  v  = 0;
                            int  vt = 0;
                            int  vn = 0;
                            bool newVertex;
                            try
                            {
                                GetVertexElements(split[1], out v, out vt, out vn);
                                newVertex = GetUniqueVertex(v, vt, vn, vertexDictionary, pmx.Vertex.Count, out int index1);
                                if (newVertex)
                                {
                                    IPXVertex vert = builder.Vertex();
                                    pmx.Vertex.Add(vert);
                                    if (v >= 0)
                                    {
                                        vert.Position = vList[v] * positionScale;
                                    }
                                    if (vt >= 0)
                                    {
                                        vert.UV = vtList[vt];
                                    }
                                    if (vn >= 0)
                                    {
                                        vert.Normal = vnList[vn];
                                    }
                                }
                                IPXVertex vertex1 = pmx.Vertex[index1];

                                GetVertexElements(split[2], out v, out vt, out vn);
                                newVertex = GetUniqueVertex(v, vt, vn, vertexDictionary, pmx.Vertex.Count, out int index2);
                                if (newVertex)
                                {
                                    IPXVertex vert = builder.Vertex();
                                    pmx.Vertex.Add(vert);
                                    if (v >= 0)
                                    {
                                        vert.Position = vList[v] * positionScale;
                                    }
                                    if (vt >= 0)
                                    {
                                        vert.UV = vtList[vt];
                                    }
                                    if (vn >= 0)
                                    {
                                        vert.Normal = vnList[vn];
                                    }
                                }
                                IPXVertex vertex2 = pmx.Vertex[index2];

                                GetVertexElements(split[3], out v, out vt, out vn);
                                newVertex = GetUniqueVertex(v, vt, vn, vertexDictionary, pmx.Vertex.Count, out int index3);
                                if (newVertex)
                                {
                                    IPXVertex vert = builder.Vertex();
                                    pmx.Vertex.Add(vert);
                                    if (v >= 0)
                                    {
                                        vert.Position = vList[v] * positionScale;
                                    }
                                    if (vt >= 0)
                                    {
                                        vert.UV = vtList[vt];
                                    }
                                    if (vn >= 0)
                                    {
                                        vert.Normal = vnList[vn];
                                    }
                                }
                                IPXVertex vertex3 = pmx.Vertex[index3];

                                GetVertexElements(split[4], out v, out vt, out vn);
                                newVertex = GetUniqueVertex(v, vt, vn, vertexDictionary, pmx.Vertex.Count, out int index4);
                                if (newVertex)
                                {
                                    IPXVertex vert = builder.Vertex();
                                    pmx.Vertex.Add(vert);
                                    if (v >= 0)
                                    {
                                        vert.Position = vList[v] * positionScale;
                                    }
                                    if (vt >= 0)
                                    {
                                        vert.UV = vtList[vt];
                                    }
                                    if (vn >= 0)
                                    {
                                        vert.Normal = vnList[vn];
                                    }
                                }
                                IPXVertex vertex4 = pmx.Vertex[index4];

                                int     faceIndex1 = 0, faceIndex2 = 0;
                                IPXFace face = builder.Face();
                                if (settings.FlipFaces)
                                {
                                    face.Vertex3 = settings.TurnQuads ? vertex3 : vertex4;
                                    face.Vertex2 = vertex2;
                                    face.Vertex1 = vertex1;
                                    currentMaterial.Faces.Add(face);
                                    faceIndex1 = currentMaterial.Faces.Count - 1;

                                    face         = builder.Face();
                                    face.Vertex1 = settings.TurnQuads ? vertex1 : vertex2;
                                    face.Vertex2 = vertex3;
                                    face.Vertex3 = vertex4;
                                    currentMaterial.Faces.Add(face);
                                    faceIndex2 = currentMaterial.Faces.Count - 1;
                                }
                                else
                                {
                                    face.Vertex1 = settings.TurnQuads ? vertex3 : vertex4;
                                    face.Vertex2 = vertex2;
                                    face.Vertex3 = vertex1;
                                    currentMaterial.Faces.Add(face);
                                    faceIndex1 = currentMaterial.Faces.Count - 1;

                                    face         = builder.Face();
                                    face.Vertex3 = settings.TurnQuads ? vertex1 : vertex2;
                                    face.Vertex2 = vertex3;
                                    face.Vertex1 = vertex4;
                                    currentMaterial.Faces.Add(face);
                                    faceIndex2 = currentMaterial.Faces.Count - 1;
                                }

                                if (settings.SaveTrianglePairs)
                                {
                                    currentMaterial.Memo += string.Format("({0},{1})", faceIndex1, faceIndex2);
                                }
                            }
                            catch (Exception ex)
                            {
                                if (progress.ReportError(ex.ToString()))
                                {
                                    return(ImportResult.Fail(ex, progress.WarningCount, progress.ErrorCount));
                                }
                            }
                        }
                        else
                        {
                            if (progress.ReportError(string.Format("The OBJ file contains a polygon with an invalid number of vertices. Currently only triangles and quads are supported. Line content: {0}", line)))
                            {
                                return(ImportResult.Fail(new InvalidOperationException("Invalid polygon"), progress.WarningCount, progress.ErrorCount));
                            }
                        }
                        break;

                    // Group assignment defines which PMX object (IPXMaterial instance) the subsequent faces belong to.
                    case "g":
                        currentMaterial      = builder.Material();
                        currentMaterial.Name = currentMaterial.NameE = line.Trim().Substring(2);
                        progress.Report("New object: " + currentMaterial.Name);
                        pmx.Material.Add(currentMaterial);
                        // Set default properties
                        currentMaterial.Diffuse = new V4(1, 1, 1, 1);
                        currentMaterial.Ambient = new V3(0.5f, 0.5f, 0.5f);
                        break;

                    // Material assignment defines which material template should be applied to the currently active PMX object. Any number of PMX objects can refer to a single material template.
                    case "usemtl":
                        if (currentMaterial == null)
                        {
                            progress.ReportWarning(string.Format("Encountered a material template reference when no active group was set.", lineNumber));
                            currentMaterial = builder.Material();
                        }
                        {
                            string      name = line.Trim().Substring(7);
                            IPXMaterial m    = currentMaterial;     // Active material
                            IPXMaterial t    = materials[name];     // Template material
                            m.Diffuse       = t.Diffuse;
                            m.Specular      = t.Specular;
                            m.Power         = t.Power;
                            m.Ambient       = t.Ambient;
                            m.Diffuse       = t.Diffuse;
                            m.SelfShadow    = t.SelfShadow;
                            m.SelfShadowMap = t.SelfShadowMap;
                            m.Shadow        = t.Shadow;
                            m.Tex           = t.Tex;
                            m.EdgeSize      = t.EdgeSize;
                            m.EdgeColor     = t.EdgeColor;
                            m.Edge          = t.Edge;
                        }
                        break;

                    // Material library, may occur multiple times in a model.
                    case "mtllib":
                        string materialLibraryName = line.Substring(7);
                        progress.Report("Importing materials from " + materialLibraryName);
                        // Try relative path
                        string materialLibraryPath = Path.Combine(Path.GetDirectoryName(path), materialLibraryName);
                        if (!File.Exists(materialLibraryPath))
                        {
                            // Try absolute path
                            materialLibraryPath = materialLibraryName;
                            if (!File.Exists(materialLibraryPath))
                            {
                                progress.ReportError(string.Format("Material library not found ({0}).", materialLibraryName));
                                break;
                            }
                        }
                        Dictionary <string, IPXMaterial> tempDict = ImportMaterials(materialLibraryPath, builder, settings, progress);
                        foreach (KeyValuePair <string, IPXMaterial> kvp in tempDict)
                        {
                            if (materials.ContainsKey(kvp.Key))
                            {
                                progress.ReportWarning(string.Format("Duplicate material {0} imported from {1} has been discarded.", kvp.Key, materialLibraryName));
                            }
                            else
                            {
                                materials.Add(kvp.Key, kvp.Value);
                            }
                        }
                        progress.Report(string.Format("Imported {0} materials from {1}.", tempDict.Count, materialLibraryName));
                        break;

                    // Smoothing group assignment (unused)
                    case "s":
                        break;

                    default:
                        break;
                    }
                }

                // Second pass for bone weights and transformations because I'm lazy
                IPXBone bone = null;
                if (settings.CreateBone != ImportSettings.CreateBoneMode.None)
                {
                    bone      = builder.Bone();
                    bone.Name = bone.NameE = pmx.ModelInfo.ModelName.Replace(' ', '_');
                }
                foreach (IPXVertex vertex in pmx.Vertex)
                {
                    // Bone
                    if (settings.CreateBone == ImportSettings.CreateBoneMode.Average)
                    {
                        bone.Position += vertex.Position;
                    }
                    vertex.Bone1   = settings.CreateBone != ImportSettings.CreateBoneMode.None ? bone : null;
                    vertex.Weight1 = 1.0f;
                    vertex.Bone2   = vertex.Bone3 = vertex.Bone4 = null;
                    vertex.Weight2 = vertex.Weight3 = vertex.Weight4 = 0;

                    // Axis swap
                    if (settings.SwapYZ)
                    {
                        float temp = vertex.Position.Y;
                        vertex.Position.Y = vertex.Position.Z;
                        vertex.Position.Z = temp;
                        temp            = vertex.Normal.Y;
                        vertex.Normal.Y = vertex.Normal.Z;
                        vertex.Normal.Z = temp;
                    }
                }
                if (settings.CreateBone == ImportSettings.CreateBoneMode.Average)
                {
                    bone.Position /= pmx.Vertex.Count;
                }
            }
            catch (OperationCanceledException)
            {
                throw;
            }
            catch (Exception ex)
            {
                if (progress.ReportError(ex.ToString()))
                {
                    return(ImportResult.Fail(ex, progress.WarningCount, progress.ErrorCount));
                }
            }
            finally
            {
                if (reader != null)
                {
                    reader.Close();
                    reader = null;
                }
            }

            return(ImportResult.Success(pmx, progress.WarningCount, progress.ErrorCount));
        }
Example #35
0
 public IPXBoneMorphOffset BoneMorphOffset(IPXBone bone, V3 translation, Q rotation)
 {
     throw new NotImplementedException();
 }
        // エントリポイント 
        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);
            }
        }
Example #37
0
 public IPXIKLink IKLink(IPXBone bone)
 {
     throw new NotImplementedException();
 }
Example #38
0
 private float NormalDist(IPXBone bone, IPXVertex vertex)
 {
     return((vertex.Position - bone.Position).Length());
 }
Example #39
0
 public static IEnumerable <IPXVertex> FromBoneWeight(IPXBone bone, IPXPmx pmx) => pmx.Vertex.Where(v => v.Bone1 == bone || v.Bone2 == bone || v.Bone3 == bone || v.Bone4 == bone);
Example #40
0
 // ボーンを表示枠に挿入
 public void InsertBoneToNode(IPXNode targetNode, IPXBone targetBone, int idx)
 {
     targetNode.Items.Insert(idx, bdx.BoneNodeItem(targetBone));
 }
Example #41
0
        /// <summary>
        /// Executes the provided XmlDocument on the PMX object.
        /// </summary>
        public static RunnerResult Execute(XmlDocument doc, IPXPmx pmx, IPXPmxBuilder builder, RunnerProgress progress)
        {
            XmlElement root = doc.DocumentElement;

            progress.Report(0, "> Execution started.");

            // Begin processing
            // Only the first level of elements are interpreted as commands.
            XmlElement[] commands = root.ChildNodes.OfType <XmlElement>().ToArray();
            for (int i = 0; i < commands.Length; ++i)
            {
                try
                {
                    XmlElement node = commands[i];

                    // The meaningful content of each case constitutes a separate block to avoid mixing variables. Might be unnecessary, but right now I'm not feeling too hot and my output WILL be sloppy.
                    // Should review this code later.
                    switch (node.Name.ToLowerInvariant())
                    {
                    // Creates a new bone with the provided properties.
                    case "bone":
                    {
                        string  name = Math.Abs(Guid.NewGuid().GetHashCode()).ToString();
                        IPXBone bone = null;

                        // Get name and check for collision
                        if (node["name"] != null)
                        {
                            name = node["name"].InnerText;

                            IPXBone existing = pmx.Bone.Where(b => b.Name == name).FirstOrDefault();
                            if (existing != null)
                            {
                                // If there is a collision, refer to the collision attribute
                                switch (node["name"].GetAttribute("collision"))
                                {
                                // If the attribute is "update" or "replace", refer to the existing bone for the rest of the command.
                                case "replace":
                                case "update":
                                    bone = existing;
                                    break;

                                // If the attribute is "skip", don't do anything with the bone and skip the command.
                                case "skip":
                                    continue;

                                // If the attribute is not valid, create a new bone and ignore the old one.
                                default:
                                    bone      = builder.Bone();
                                    bone.Name = bone.NameE = name;
                                    break;
                                }
                            }
                            else
                            {
                                bone      = builder.Bone();
                                bone.Name = bone.NameE = name;
                            }
                        }
                        else
                        {
                            bone      = builder.Bone();
                            bone.Name = bone.NameE = name;
                        }

                        if (node["position"] != null)
                        {
                            bone.Position = node["position"].GetV3();
                        }
                        if (node["translation"] != null)
                        {
                            bone.IsTranslation = bool.TryParse(node["translation"].InnerText, out bool translation) ? translation : false;
                        }
                        if (node["parent"] != null)
                        {
                            bone.Parent = Selector.Bone.Selector(node["parent"], pmx).FirstOrDefault();
                        }
                        if (node["axis"] != null)
                        {
                            V3 v = node["axis"].GetV3();
                            v.Normalize();
                            bone.IsFixAxis = true;
                            bone.FixAxis   = v;
                        }
                        if (node["weight"] != null)
                        {
                            //IEnumerable<IPXVertex> vertices = Selector.Vertex.SelectorList(node["weight"].ChildNodes, pmx);
                            IEnumerable <IPXVertex> vertices = Selector.Vertex.SelectorNode(node["weight"], pmx);
                            foreach (IPXVertex v in vertices)
                            {
                                v.Bone1   = bone;
                                v.Weight1 = 1;
                                v.Bone2   = v.Bone3 = v.Bone4 = null;
                                v.Weight2 = v.Weight3 = v.Weight4 = 0;
                            }
                        }
                        pmx.Bone.Add(bone);
                        progress.Report(Percent(i + 1, commands.Length), string.Format("[bone] Added new bone {0}.", bone.Name));
                    }
                    break;

                    // Assigns the selected vertices to the selected bone using BDEF1.
                    case "weight":
                    {
                        IPXBone bone = null;
                        if (node["target"] != null)
                        {
                            bone = Selector.Bone.Selector(node["target"], pmx).FirstOrDefault();
                            if (bone == null)
                            {
                                progress.Report(Percent(i + 1, commands.Length), string.Format("[weight] Bone was not found.", node["target"].InnerText));
                                break;
                            }
                        }
                        else
                        {
                            progress.Report(Percent(i + 1, commands.Length), "[weight] Bone selector was not specified.");
                            break;
                        }

                        // Set vertex weights
                        if (node["select"] == null)
                        {
                            progress.Report(Percent(i + 1, commands.Length), "[weight] No vertices were selected.");
                            break;
                        }
                        IEnumerable <IPXVertex> vertices = Selector.Vertex.SelectorNode(node["select"], pmx);
                        foreach (IPXVertex v in vertices)
                        {
                            v.Bone1   = bone;
                            v.Weight1 = 1;
                            v.Bone2   = v.Bone3 = v.Bone4 = null;
                            v.Weight2 = v.Weight3 = v.Weight4 = 0;
                        }

                        progress.Report(Percent(i + 1, commands.Length), string.Format("[weight] Weighted {0} vertices to {1} ({2}).", vertices.Count(), bone.Name, bone.NameE));
                    }
                    break;

                    // Creates a new UV morph.
                    case "uvmorph":
                    {
                        // The morph's properties are defined in attributes.
                        IPXMorph morph = builder.Morph();
                        morph.Kind = MorphKind.UV;

                        // Set the UV channel
                        if (int.TryParse(node.GetAttribute("channel"), out int ch))
                        {
                            switch (ch)
                            {
                            case 1:
                                morph.Kind = MorphKind.UVA1;
                                break;

                            case 2:
                                morph.Kind = MorphKind.UVA2;
                                break;

                            case 3:
                                morph.Kind = MorphKind.UVA3;
                                break;

                            case 4:
                                morph.Kind = MorphKind.UVA4;
                                break;

                            default:
                                morph.Kind = MorphKind.UV;
                                break;
                            }
                        }

                        // Set the group panel
                        if (int.TryParse(node.GetAttribute("group"), out int group) && group <= 4 && group >= 0)
                        {
                            morph.Panel = group;
                        }
                        else
                        {
                            switch (node.GetAttribute("group").ToLowerInvariant())
                            {
                            case "hidden":
                            case "hide":
                            case "none":
                            case "0":
                                morph.Panel = 0;
                                break;

                            case "eyebrow":
                            case "eyebrows":
                            case "1":
                                morph.Panel = 1;
                                break;

                            case "eye":
                            case "eyes":
                            case "2":
                                morph.Panel = 2;
                                break;

                            case "mouth":
                            case "3":
                                morph.Panel = 3;
                                break;

                            default:
                                morph.Panel = 4;
                                break;
                            }
                        }

                        // Set the name, ignore collisions
                        if (node.HasAttribute("name"))
                        {
                            morph.Name = morph.NameE = node.GetAttribute("name");
                        }
                        else
                        {
                            morph.Name = morph.NameE = morph.GetHashCode().ToString();
                        }

                        // Each morph contains one or more steps. Each step has its own selectors and transforms, which are applied independently.
                        foreach (XmlElement step in node.ChildNodes.OfType <XmlElement>().Where(el => el.Name.ToLowerInvariant() == "step"))
                        {
                            // Skip steps that have no selectors
                            if (step["select"] == null)
                            {
                                continue;
                            }
                            // Select vertices
                            IEnumerable <IPXVertex> vertices = Selector.Vertex.SelectorNode(step["select"], pmx);
                            foreach (XmlElement e in step)
                            {
                                switch (e.Name.ToLowerInvariant())
                                {
                                case "pan":
                                case "translate":
                                {
                                    V2 v = e.GetV2();
                                    foreach (IPXVertex vertex in vertices)
                                    {
                                        IPXUVMorphOffset offset = builder.UVMorphOffset();
                                        offset.Vertex = vertex;
                                        offset.Offset = new V4(v.X, v.Y, 0, 0);
                                        morph.Offsets.Add(offset);
                                    }
                                }
                                break;

                                case "rotate":              // TODO: UV morph rotation
                                case "scale":               // TODO: UV morph scaling
                                default:
                                    break;
                                }
                            }
                        }

                        pmx.Morph.Add(morph);
                        progress.Report(Percent(i + 1, commands.Length), string.Format("[uvmorph] Created UV morph {0} with {1} offsets.", morph.Name, morph.Offsets.Count));
                    }
                    break;

                    // No particular functionality, testing only.
                    case "test":
                    {
                        //foreach (IPXMorph morph in pmx.Morph.Where(m => m.Kind == MorphKind.UV))
                        //{
                        //    foreach (IPXUVMorphOffset o in morph.Offsets)
                        //    {
                        //        _report(string.Format("{0:f2}, {1:f2}, {2:f2}, {3:f2}", o.Offset.X, o.Offset.Y, o.Offset.Z, o.Offset.W), -1);
                        //    }
                        //}
                    }
                    break;

                    // Sets up the selected vertices for use with AutoLuminous.
                    case "autoluminous":
                    {
                        if (node["select"] == null)
                        {
                            progress.Report(Percent(i + 1, commands.Length), "[weight] No vertices were selected.");
                            break;
                        }
                        IEnumerable <IPXVertex> vertices = Selector.Vertex.SelectorNode(node["select"], pmx);

                        // Set required values.
                        pmx.Header.UVACount = Math.Max(pmx.Header.UVACount, 3);

                        // UV1
                        int   texture        = 0;
                        int   hsv            = 0;
                        float flashFrequency = 0;
                        // UV2
                        V4 baseColor = new V4(0, 0, 0, 0);
                        // UV3
                        float texSubtract = 0;
                        float flashBias   = 0;
                        float push        = 0;

                        // Base emissive color
                        if (node["color"] != null)
                        {
                            baseColor = node["color"].GetV4();
                        }

                        // Base emissive power
                        if (node["power"] != null)
                        {
                            baseColor.W = node["power"].GetSingle();
                        }

                        if (node["texture"] != null)
                        {
                            int.TryParse(node["texture"].InnerText, System.Globalization.NumberStyles.Integer, System.Globalization.NumberFormatInfo.InvariantInfo, out texture);
                        }

                        if (node["colormode"] != null)
                        {
                            switch (node["colormode"].InnerText.ToLowerInvariant())
                            {
                            case "hsv":
                                hsv = 10;
                                break;

                            default:
                                hsv = 0;
                                break;
                            }
                        }

                        if (node["flash"] != null)
                        {
                            float.TryParse(node["flash"].GetAttribute("bias"), System.Globalization.NumberStyles.Float, System.Globalization.NumberFormatInfo.InvariantInfo, out flashBias);
                            flashFrequency = node["flash"].GetSingle();
                        }

                        if (node["subtract"] != null)
                        {
                            texSubtract = node["subtract"].GetSingle();
                        }

                        if (node["push"] != null)
                        {
                            push = node["push"].GetSingle();
                        }

                        foreach (IPXVertex v in vertices)
                        {
                            v.UVA1.X = 0.2f;            // Required value
                            v.UVA1.Y = 0.7f;            // Required value
                            v.UVA1.Z = flashFrequency;
                            v.UVA1.W = texture + hsv;

                            v.UVA2 = baseColor;

                            v.UVA3.X = texSubtract;
                            v.UVA3.Y = flashBias;
                            v.UVA3.Z = push;
                        }
                    }
                    break;

                    // Creates a vertex morph for AutoLuminous properties.
                    case "almorph":
                    {
                        if (node["select"] == null)
                        {
                            progress.Report(Percent(i + 1, commands.Length), "[weight] No vertices were selected.");
                            break;
                        }
                        HashSet <IPXVertex> vertices = new HashSet <IPXVertex>(Selector.Vertex.SelectorNode(node["select"], pmx));

                        V4 color = new V4();

                        if (node["color"] != null)
                        {
                            color = node["color"].GetV4();
                        }

                        // TODO: Implement the rest of the AL properties in ALMorph

                        IPXMorph morph = builder.Morph();
                        morph.Kind = MorphKind.UVA2;
                        if (node.HasAttribute("name"))
                        {
                            morph.Name = morph.NameE = node.GetAttribute("name");
                        }
                        else
                        {
                            morph.Name = morph.NameE = morph.GetHashCode().ToString();
                        }

                        foreach (IPXVertex v in vertices)
                        {
                            // Set required values in case the vertex isn't already AL-enabled
                            v.UVA1.X = 0.2f;
                            v.UVA1.Y = 0.7f;
                            // Create the offset
                            morph.Offsets.Add(builder.UVMorphOffset(v, color));
                        }
                    }
                    break;

                    // Sets environment variables.
                    case "settings":
                    {
                        foreach (XmlElement child in node.ChildNodes.OfType <XmlElement>())
                        {
                            switch (child.Name.ToLowerInvariant())
                            {
                            case "exception":
                                break;

                            case "regex":
                                bool regexCI = GlobalSettings.RegexCaseInsensitive;
                                bool.TryParse(child.GetAttributeCI("caseinsensitive"), out regexCI);
                                break;

                            case "colortype":
                                GlobalSettings.ColorIsFloat = child.InnerText.ToLowerInvariant() == "float";
                                break;

                            default:
                                break;
                            }
                        }
                    }
                    break;

                    // Displays a MessageBox with the provided content. Optionally perform certain actions based on user input.
                    case "mbox":
                    case "messagebox":
                    case "prompt":
                    {
                        if (int.TryParse(node.GetAttributeCI("skip"), out int skipNumber) && skipNumber > 0)
                        {
                            StringBuilder sb = new StringBuilder(string.Format("Would you like to skip the following {0} command(s)?\n", skipNumber));
                            for (int j = 1; j <= skipNumber; ++j)
                            {
                                sb.Append(commands[i + j].Name);
                            }
                            MessageBox.Show(sb.ToString(), "Prompt: skip", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                        }
                        else
                        {
                            MessageBox.Show(node.InnerText, "Message", MessageBoxButtons.OK, MessageBoxIcon.Information);
                        }
                    }
                    break;

                    // Prints a line in the console.
                    case "echo":
                    case "print":
                        progress.Report(Percent(i + 1, commands.Length), node.InnerText);
                        break;

                    default:
                        progress.Report(Percent(i + 1, commands.Length), "Skipping unknown command " + node.Name);
                        break;
                    }
                }
                catch (Exception ex)
                {
                    if (GlobalSettings.Exception == GlobalSettings.ErrorHandling.Ask)
                    {
                        if (MessageBox.Show(string.Format("The following exception has occured:\n\n{0}\n\nWould you like to continue execution?", ex.ToString()), "Exception", System.Windows.Forms.MessageBoxButtons.YesNo, System.Windows.Forms.MessageBoxIcon.Error) == System.Windows.Forms.DialogResult.No)
                        {
                            return(RunnerResult.Fail);
                        }
                    }
                    else if (GlobalSettings.Exception == GlobalSettings.ErrorHandling.Abort)
                    {
                        return(RunnerResult.Fail);
                    }
                }
            }

            // If control has reached this point, the execution is considered successful.
            return(RunnerResult.Success);
        }
Example #42
0
 // targetBoneの直前にmovingBoneを移動
 // 返り値は移動できたかどうか
 public bool MoveBoneBefore(IPXBone targetBone, IPXBone movingBone)
 {
     bone.Remove(movingBone);
     return InsertBoneBefore(targetBone, movingBone);
 }