示例#1
0
        //
        // Expand()
        //

        /// <summary>
        /// smesh1, smesh2の輪郭をずらして重ねる。輪郭に制御点をおいてARAPする
        /// curveOffset, curveLengthは切り口付近の補間に使う部分曲線
        /// </summary>
        static void Expand(
            PatchSkeletalMesh patch1, PatchSkeletalMesh patch2, PatchSkeleton refSkeleton,
            PatchSection section1, PatchSection section2, PatchSkeletonBone bone,
            float curveLength, float curveBuffer)
        {
            // メッシュを固定
            patch1.mesh.FreezeMesh(true);
            patch2.mesh.FreezeMesh(true);

            List <PatchVertex> rawPath1 = GetPath(patch1);
            List <PatchVertex> rawPath2 = GetPath(patch2);
            List <PointF>      path1    = rawPath1.Select(v => v.position).ToList();
            List <PointF>      path2    = rawPath2.Select(v => v.position).ToList();

            // 切り口に隣接する2曲線をそれぞれ取得
            var rawCurves1 = section2adjCurves(rawPath1, section1);
            var rawCurves2 = section2adjCurves(rawPath2, section2);

            if (rawCurves1 == null || rawCurves2 == null)
            {
                return;
            }

            var trimCurves1 = TrimCurves(rawPath1, rawCurves1, 0, curveLength);
            var trimCurves2 = TrimCurves(rawPath2, rawCurves2, 0, curveLength);

            PatchSkeletonBone refBone = RefBone(refSkeleton, bone);
            var sorted1 = GetSortedCurves(path1, trimCurves1, refBone);
            var sorted2 = GetSortedCurves(path2, trimCurves2, refBone);

            if (sorted1.Count != 2 || sorted2.Count != 2)
            {
                return;
            }

            // patch1の制御点
            patch1.mesh.ClearControlPoints();
            for (int i = 0; i < 2; i++)
            {
                foreach (var p in sorted1[i])
                {
                    patch1.mesh.AddControlPoint(p, p);
                }
            }
            patch1.mesh.BeginDeformation();

            // patch2の制御点
            patch2.mesh.ClearControlPoints();
            for (int i = 0; i < 2; i++)
            {
                foreach (var p in sorted2[i])
                {
                    patch2.mesh.AddControlPoint(p, p);
                }
            }
            patch2.mesh.BeginDeformation();

            // 第一要素、第二要素がそれぞれボーンにとって同じ側の切り口となるように並び替える
            // 切り口に近づく向きに点が並んでいる
            float h10     = CurveHeight(sorted1[0], refBone);
            float h11     = CurveHeight(sorted1[1], refBone);
            float h20     = CurveHeight(sorted2[0], refBone);
            float h21     = CurveHeight(sorted2[1], refBone);
            var   curve10 = sorted1[0].ToList();
            var   curve11 = sorted1[1].ToList();
            var   curve20 = sorted2[0].ToList();
            var   curve21 = sorted2[1].ToList();

            // curveの重心を揃える
            PointF x, y;

            BoneCoordinate(refBone, out x, out y);

            float c0   = (h10 + h20) * 0.5f;
            float dy10 = c0 - h10;

            for (int i = 0; i < curve10.Count; i++)
            {
                curve10[i] = new PointF(curve10[i].X + dy10 * y.X, curve10[i].Y + dy10 * y.Y);
            }
            float dy11 = c0 - h20;

            for (int i = 0; i < curve20.Count; i++)
            {
                curve20[i] = new PointF(curve20[i].X + dy11 * y.X, curve20[i].Y + dy11 * y.Y);
            }

            float c1   = (h11 + h21) * 0.5f;
            float dy20 = c1 - h11;

            for (int i = 0; i < curve11.Count; i++)
            {
                curve11[i] = new PointF(curve11[i].X + dy20 * y.X, curve11[i].Y + dy20 * y.Y);
            }
            float dy21 = c1 - h21;

            for (int i = 0; i < curve21.Count; i++)
            {
                curve21[i] = new PointF(curve21[i].X + dy21 * y.X, curve21[i].Y + dy21 * y.Y);
            }

            // curveをエルミート保管して繋げる
            var ends0 = new[] { curve10[0], curve10.Last(), curve20[0], curve20.Last() };
            int min0, max0;

            FMath.GetMinElement(ends0, p => FMath.ParameterOnLine(p, refBone.src.position, refBone.dst.position), out min0);
            FMath.GetMinElement(ends0, p => - FMath.ParameterOnLine(p, refBone.src.position, refBone.dst.position), out max0);

            var ends1 = new[] { curve11[0], curve11.Last(), curve21[0], curve21.Last() };
            int min1, max1;

            FMath.GetMinElement(ends1, p => FMath.ParameterOnLine(p, refBone.src.position, refBone.dst.position), out min1);
            FMath.GetMinElement(ends1, p => - FMath.ParameterOnLine(p, refBone.src.position, refBone.dst.position), out max1);

            PointF[] es = new[] {
                ends0[min0],
                ends1[min1],
                ends0[max0],
                ends1[max1],
            };
            PointF[] vs = new[] {
                new PointF(curve10[0].X - curve10[curve10.Count - 1].X, curve10[0].Y - curve10[curve10.Count - 1].Y),
                new PointF(curve11[0].X - curve11[curve11.Count - 1].X, curve11[0].Y - curve11[curve11.Count - 1].Y),
                new PointF(-(curve20[0].X - curve20[curve20.Count - 1].X), -(curve20[0].Y - curve20[curve20.Count - 1].Y)),
                new PointF(-(curve21[0].X - curve21[curve21.Count - 1].X), -(curve21[0].Y - curve21[curve21.Count - 1].Y)),
            };
            float[] ps = new[] {
                FMath.ParameterOnLine(es[0], refBone.src.position, refBone.dst.position),
                FMath.ParameterOnLine(es[1], refBone.src.position, refBone.dst.position),
                FMath.ParameterOnLine(es[2], refBone.src.position, refBone.dst.position),
                FMath.ParameterOnLine(es[3], refBone.src.position, refBone.dst.position),
            };

            for (int i = 0; i < 2; i++)
            {
                var   e1     = es[i];
                var   v1     = vs[i];
                float param1 = ps[i];

                var   e2     = es[i + 2];
                var   v2     = vs[i + 2];
                float param2 = ps[i + 2];

                if (Math.Abs(param2 - param1) <= 1e-4)
                {
                    continue;
                }
                float paramRatio = 1 / (param2 - param1);

                for (int j = 0; j < sorted1[i].Count; j++)
                {
                    float  param = FMath.ParameterOnLine(sorted1[i][j], refBone.src.position, refBone.dst.position);
                    float  t     = (param - param1) * paramRatio;
                    PointF to    = FMath.HelmitteInterporate(e1, v1, e2, v2, t);
                    patch1.mesh.TranslateControlPoint(sorted1[i][j], to, false);
                }
                for (int j = 0; j < sorted2[i].Count; j++)
                {
                    float  param = FMath.ParameterOnLine(sorted2[i][j], refBone.src.position, refBone.dst.position);
                    float  t     = (param - param1) * paramRatio;
                    PointF to    = FMath.HelmitteInterporate(e1, v1, e2, v2, t);
                    patch2.mesh.TranslateControlPoint(sorted2[i][j], to, false);
                }
            }

            // 変形
            patch1.mesh.FlushDefomation();
            patch2.mesh.FlushDefomation();

            // 変形終了
            patch1.mesh.EndDeformation();
            patch2.mesh.EndDeformation();
        }
示例#2
0
        //
        // Expand()
        //

        /// <summary>
        /// smesh1, smesh2の輪郭をずらして重ねる。輪郭に制御点をおいてARAPする
        /// </summary>
        static void Expand(PatchSkeletalMesh smesh1, PatchSkeletalMesh smesh2, PatchSkeleton skl, PatchSection section1, PatchSection section2, PatchSkeletonBone bone)
        {
            List <PatchVertex> rawPath1 = GetPath(smesh1);
            List <PatchVertex> rawPath2 = GetPath(smesh2);
            List <PointF>      path1    = rawPath1.Select(v => v.position).ToList();
            List <PointF>      path2    = rawPath2.Select(v => v.position).ToList();

            //
            // 輪郭を変形できるように制御点を作り直す
            //

            // smesh1
            smesh1.mesh.ClearControlPoints();
            foreach (var v in rawPath1)
            {
                smesh1.mesh.AddControlPoint(v.position, v.orgPosition);
            }
            smesh1.mesh.BeginDeformation();

            // smesh2
            smesh2.mesh.ClearControlPoints();
            foreach (var v in rawPath2)
            {
                smesh2.mesh.AddControlPoint(v.position, v.orgPosition);
            }
            smesh2.mesh.BeginDeformation();


            //
            // 切り口に隣接する2曲線を各切り口について取得し、これらが重なるように輪郭をずらす
            //

            // 切り口に隣接する2曲線をそれぞれ取得
            var rawCurves1 = SectionToAdjuscentCurves(path1, section1, 5, 30);
            var rawCurves2 = SectionToAdjuscentCurves(path2, section2, 5, 30);

            if (rawCurves1 == null || rawCurves2 == null)
            {
                return;
            }

            PatchSkeletonBone refBone = null;

            foreach (var b in skl.bones)
            {
                if (bone == b)
                {
                    refBone = b;
                    break;
                }
            }

            // curves1, curves2の第一要素、第二要素がそれぞれ向かい合う(ボーンにとって同じ側の)切り口となるように並び替える
            var curves1 = GetSortedCurves(path1, rawCurves1, refBone);
            var curves2 = GetSortedCurves(path2, rawCurves2, refBone);

            if (curves1.Count != 2 || curves2.Count != 2)
            {
                return;
            }

            // curves1, curves2の移動履歴を記録
            List <Tuple <PointF, PointF> > move1 = new List <Tuple <PointF, PointF> >();
            List <Tuple <PointF, PointF> > move2 = new List <Tuple <PointF, PointF> >();

            // 対応する曲線間で2点がかぶる(同じ座標になる)ように変形。
            for (int i = 0; i < 2; i++)
            {
                var p1 = curves1[i].First();
                var v1 = new PointF(p1.X - curves1[i].Last().X, p1.Y - curves1[i].Last().Y);
                var p2 = curves2[i].First();
                var v2 = new PointF(curves2[i].Last().X - p2.X, curves2[i].Last().Y - p2.Y);

                // 2点かぶらせる
                int cnt = curves1[i].Count + curves2[i].Count - 2;
                if (cnt <= 1)
                {
                    continue;
                }

                for (int j = 0; j < curves1[i].Count; j++)
                {
                    PointF to = FMath.HelmitteInterporate(p1, v1, p2, v2, (float)j / (cnt - 1));
                    if (j == curves1[i].Count - 1)
                    {
                        move1.Add(new Tuple <PointF, PointF>(curves1[i][j], to));
                    }
                    smesh1.mesh.TranslateControlPoint(curves1[i][j], to, false);
                }
                for (int j = 0; j < curves2[i].Count; j++)
                {
                    PointF to = FMath.HelmitteInterporate(p1, v1, p2, v2, (float)(-j + cnt - 1) / (cnt - 1));
                    if (j == curves2[i].Count - 1)
                    {
                        move2.Add(new Tuple <PointF, PointF>(curves2[i][j], to));
                    }
                    smesh2.mesh.TranslateControlPoint(curves2[i][j], to, false);
                }
            }

            //
            // 各曲線の動きに合わせて切り口を動かす
            //
            List <PointF> sections1 = new List <PointF>();

            for (int i = section1.First + 1; i < section1.First + section1.Length - 1; i++)
            {
                sections1.Add(path1[FMath.Rem(i, path1.Count)]);
            }
            List <PointF> newSection1 = ARAPDeformation.ARAPDeformation.Deform(sections1, move1);

            if (newSection1.Count == sections1.Count)
            {
                for (int i = 0; i < newSection1.Count; i++)
                {
                    smesh1.mesh.TranslateControlPoint(sections1[i], newSection1[i], false);
                }
            }

            List <PointF> sections2 = new List <PointF>();

            for (int i = section2.First + 1; i < section2.First + section2.Length - 1; i++)
            {
                sections2.Add(path2[FMath.Rem(i, path2.Count)]);
            }
            List <PointF> newSection2 = ARAPDeformation.ARAPDeformation.Deform(sections2, move2);

            if (newSection2.Count == sections2.Count)
            {
                for (int i = 0; i < newSection2.Count; i++)
                {
                    smesh2.mesh.TranslateControlPoint(sections2[i], newSection2[i], false);
                }
            }

            //
            // 変形
            //
            smesh1.mesh.FlushDefomation();
            smesh2.mesh.FlushDefomation();

            //
            // 変形終了
            //
            smesh1.mesh.EndDeformation();
            smesh2.mesh.EndDeformation();
        }
示例#3
0
        private static void ExpandSegments(List <SegmentMeshInfo> meshes, SkeletonAnnotation an, List <ConnectPair> pairs)
        {
            int _cnt = 0;

            foreach (var m in meshes)
            {
                if (m.arap == null)
                {
                    continue;
                }
                m.arap.controlPoints.Clear();
                SegmentMeshInfo.SetPathControlPoints(m.arap);
                m.arap.BeginDeformation();
                m.arap.ToBitmap().Save("../../../Test2/" + (_cnt++) + ".png");
            }

            foreach (var b in an.bones)
            {
                foreach (var p in pairs)
                {
                    if (p.bone != b)
                    {
                        continue;
                    }

                    var m1 = p.meshInfo1;
                    var m2 = p.meshInfo2;
                    if (m1.arap == null || m2.arap == null)
                    {
                        continue;
                    }

                    var path1   = m1.arap.GetPath();
                    var path2   = m2.arap.GetPath();
                    var ranges1 = SectionToCurves(path1, p.sectionRange1, 5, 30);
                    var ranges2 = SectionToCurves(path2, p.sectionRange2, 5, 30);
                    if (ranges1 == null || ranges2 == null)
                    {
                        continue;
                    }

                    var curves1 = GetSortedCurves(path1, ranges1, b);
                    var curves2 = GetSortedCurves(path2, ranges2, b);
                    if (curves1.Count != 2 || curves2.Count != 2)
                    {
                        continue;
                    }

                    List <Tuple <PointF, PointF> > move1 = new List <Tuple <PointF, PointF> >();
                    List <Tuple <PointF, PointF> > move2 = new List <Tuple <PointF, PointF> >();

                    for (int i = 0; i < 2; i++)
                    {
                        var p1 = curves1[i].First();
                        var v1 = new PointF(p1.X - curves1[i].Last().X, p1.Y - curves1[i].Last().Y);
                        var p2 = curves2[i].First();
                        var v2 = new PointF(curves2[i].Last().X - p2.X, curves2[i].Last().Y - p2.Y);

                        // 2点かぶらせる
                        int cnt = curves1[i].Count + curves2[i].Count - 2;
                        if (cnt <= 1)
                        {
                            continue;
                        }

                        for (int j = 0; j < curves1[i].Count; j++)
                        {
                            PointF to = FMath.HelmitteInterporate(p1, v1, p2, v2, (float)j / (cnt - 1));
                            if (j == curves1[i].Count - 1)
                            {
                                move1.Add(new Tuple <PointF, PointF>(curves1[i][j], to));
                            }
                            m1.arap.TranslateControlPoint(curves1[i][j], to, false);
                        }
                        for (int j = 0; j < curves2[i].Count; j++)
                        {
                            PointF to = FMath.HelmitteInterporate(p1, v1, p2, v2, (float)(-j + cnt - 1) / (cnt - 1));
                            if (j == curves2[i].Count - 1)
                            {
                                move2.Add(new Tuple <PointF, PointF>(curves2[i][j], to));
                            }
                            m2.arap.TranslateControlPoint(curves2[i][j], to, false);
                        }
                    }

                    List <PointF> sections1 = new List <PointF>();
                    List <PointF> sections2 = new List <PointF>();

                    for (int i = p.sectionRange1.First + 1; i < p.sectionRange1.First + p.sectionRange1.Length - 1; i++)
                    {
                        sections1.Add(path1[Rem(i, path1.Count)]);
                    }
                    for (int i = p.sectionRange2.First + 1; i < p.sectionRange2.First + p.sectionRange2.Length - 1; i++)
                    {
                        sections2.Add(path2[Rem(i, path2.Count)]);
                    }

                    List <PointF> newSection1 = ARAPDeformation.Deform(sections1, move1);
                    List <PointF> newSection2 = ARAPDeformation.Deform(sections2, move2);

                    if (newSection1.Count == sections1.Count)
                    {
                        for (int i = 0; i < newSection1.Count; i++)
                        {
                            m1.arap.TranslateControlPoint(sections1[i], newSection1[i], false);
                        }
                    }
                    if (newSection2.Count == sections2.Count)
                    {
                        for (int i = 0; i < newSection2.Count; i++)
                        {
                            m2.arap.TranslateControlPoint(sections2[i], newSection2[i], false);
                        }
                    }

                    m1.arap.FlushDefomation();
                    m2.arap.FlushDefomation();
                }
            }

            foreach (var m in meshes)
            {
                if (m.arap == null)
                {
                    continue;
                }
                m.arap.EndDeformation();
            }
        }