Exemplo n.º 1
0
        public static void Fitting(PatchSkeletalMesh smesh, PatchSkeleton skl)
        {
            FTimer.Resume("Fitting:SetCtrl");
            // スケルトンに合わせて制御点を移動
            foreach (var kv in smesh.skeletalControlPointDict)
            {
                PatchSkeletonBone b      = kv.Key;
                List <PointF>     orgPts = kv.Value;
                PatchSkeletonBone br     = CorrespondingBone(skl, b);

                if (br == null)
                {
                    continue;
                }
                if (orgPts.Count <= 1)
                {
                    continue;
                }

                for (int i = 0; i < orgPts.Count; i++)
                {
                    float t = (float)i / (orgPts.Count - 1);

                    // smesh.skeletalControlPointExpandToXXXの値にしたがって、src, dst方向にそれぞれ伸長させる
                    float exSrc = smesh.endJoints.Contains(b.src.name) ? smesh.srcStretchRatio : 0;
                    float exDst = smesh.endJoints.Contains(b.dst.name) ? smesh.dstStretchRatio : 0;
                    float dx    = br.dst.position.X - br.src.position.X;
                    float dy    = br.dst.position.Y - br.src.position.Y;
                    t *= 1 + exSrc + exDst;
                    float lx = dx * t;
                    float ly = dy * t;
                    float ox = -dx * exSrc;
                    float oy = -dy * exSrc;
                    float x  = br.src.position.X + ox + lx;
                    float y  = br.src.position.Y + oy + ly;

//                    float x = br.src.position.X * (1 - t) + br.dst.position.X * t;
//                    float y = br.src.position.Y * (1 - t) + br.dst.position.Y * t;

                    PatchControlPoint c = smesh.mesh.FindControlPoint(orgPts[i]);
                    if (c == null)
                    {
                        continue;
                    }
                    smesh.mesh.TranslateControlPoint(c.position, new PointF(x, y), false);
                }

                // スケルトン(mesh.skl)も動かす
                b.src.position = br.src.position;
                b.dst.position = br.dst.position;
            }
            FTimer.Pause("Fitting:SetCtrl");

            // 制御点の移動を反映してメッシュ変形
            FTimer.Resume("Fitting:FlushDefomation");
            smesh.mesh.FlushDefomation();
            FTimer.Pause("Fitting:FlushDefomation");
        }
Exemplo n.º 2
0
        public void FlushDefomation()
        {
            FTimer.Resume("FlushDefomation:begin");
            // 制御点をPatchMesh, ARAPで同期させる
            arap.UpdateControlPoint(controlPoints.Select(c => c.position).ToList());
            FTimer.Pause("FlushDefomation:begin");

            FTimer.Resume("FlushDefomation:flush");
            // ARAP変形
            arap.FlushDefomation();
            FTimer.Pause("FlushDefomation:flush");

            FTimer.Resume("FlushDefomation:end");
            // 結果を取得
            List <PointF> ptList = arap.CopyMeshPointList();

            for (int i = 0; i < vertices.Count; i++)
            {
                vertices[i].position = ptList[i];
            }
            FTimer.Pause("FlushDefomation:end");
        }
Exemplo n.º 3
0
        void RigidMLS()
        {
            if (controls.Count < 3)
                return;

            if (weights == null || A00 == null || A01 == null || A10 == null || A11 == null || D == null)
                return;
#if USE_PARALLEL_FOR
            System.Threading.Tasks.Parallel.For(0, meshPointList.Count, vIdx =>
#else
            for (int vIdx = 0; vIdx < meshPointList.Count; vIdx++)
#endif
            {
                FTimer.Resume("1");
                int offset = vIdx * controls.Count;

                // 追加 2014/11/08
                int nonzeroCnt = 0;
                for (int i = 0; i < controls.Count; i++)
                    if (weights[i + offset] != 0)
                        nonzeroCnt++;
                FTimer.Pause("1");
                if (nonzeroCnt <= 1)
                {
#if USE_PARALLEL_FOR
                    return;
#else
                    continue;
#endif
                }
                FTimer.Resume("2");
                bool flg = false;
                for (int i = offset; i < offset + controls.Count; i++)
                {
                    if (float.IsInfinity(weights[i]))
                    {
                        // infに飛んでたらcontrols[i]自体を返す
                        meshPointList[vIdx] = controls[i - offset];
                        flg = true;
                        break;
                    }
                }
                FTimer.Pause("2");
                if (flg)
                {
#if USE_PARALLEL_FOR
                    return;
#else
                    continue;
#endif
                }
                FTimer.Resume("3");
                PointF? Qa = AverageWeight(controls, weights, vIdx);
                FTimer.Pause("3");
                if (Qa == null || !Qa.HasValue)
                {
#if USE_PARALLEL_FOR
                    return;
#else
                    continue;
#endif
                }
                FTimer.Resume("4");
                meshPointList[vIdx] = Qa.Value;
                float fx = 0;
                float fy = 0;
                for (int i = 0; i < controls.Count; i++)
                {
                    int idx = i + vIdx * controls.Count;
                    float qx = controls[i].X - Qa.Value.X;
                    float qy = controls[i].Y - Qa.Value.Y;
                    fx += qx * A00[idx] + qy * A10[idx];
                    fy += qx * A01[idx] + qy * A11[idx];
                }
                FTimer.Pause("4");
                FTimer.Resume("5");
                float lenD = (float)Math.Sqrt(D[vIdx].X * D[vIdx].X + D[vIdx].Y * D[vIdx].Y);
                float lenf = (float)Math.Sqrt(fx * fx + fy * fy);
                float k = lenD / (0.01f + lenf);
                PointF pt = meshPointList[vIdx];
                pt.X += fx * k;
                pt.Y += fy * k;
                meshPointList[vIdx] = pt;
                FTimer.Pause("5");
            }