Esempio n. 1
0
def round_bezier_mmd(target: MVector2D):
    t2 = MVector2D()

    # XとYをそれぞれ整数(0-127)に丸める
    t2.setX(round_integer(target.x() * INTERPOLATION_MMD_MAX))
    t2.setY(round_integer(target.y() * INTERPOLATION_MMD_MAX))

    return t2
Esempio n. 2
0
 def test_scale_bezier(self):
     s1, s2, s3, s4 = MBezierUtils.scale_bezier(MVector2D(0.2, 0.7),
                                                MVector2D(0.3, -0.5),
                                                MVector2D(0.4, 1.2),
                                                MVector2D(1.2, 2))
     print("s1: %s" % s1)
     print("s2: %s" % s2)
     print("s3: %s" % s3)
     print("s4: %s" % s4)
Esempio n. 3
0
def convert_catmullrom_2_bezier(xs: list, ys: list):

    bz_x = []
    bz_y = []

    for x0, x1, x2, x3, y0, y1, y2, y3 in zip(xs[:-3], xs[1:-2], xs[2:-1],
                                              xs[3:], ys[:-3], ys[1:-2],
                                              ys[2:-1], ys[3:]):
        p0 = None if not x0 and not y0 else MVector2D(x0, y0)
        p1 = MVector2D(x1, y1)
        p2 = MVector2D(x2, y2)
        p3 = None if not x3 and not y3 else MVector2D(x3, y3)
        B = None
        C = None

        if not p0 and not p3:
            # 両方ない場合、無視
            continue

        if not p0 and p3:
            bz_x.append(p1.x())
            bz_y.append(p1.y())

            # p0が空の場合、始点
            B = (p1 * (1 / 2)) - p2 + (p3 * (1 / 2))
            C = (p1 * (-3 / 2)) + (p2 * 2) - (p3 * (1 / 2))

        if p0 and not p3:
            # p3が空の場合、終点
            B = (p0 * (1 / 2)) - p1 + (p2 * (1 / 2))
            C = (p0 * (-1 / 2)) + (p2 * (1 / 2))

        if p0 and p3:
            # それ以外は通過点
            B = p0 - (p1 * (5 / 2)) + (p2 * (4 / 2)) - (p3 * (1 / 2))
            C = (p0 * (-1 / 2)) + (p2 * (1 / 2))

        if not B or not C:
            logger.warning("p0: %s, p1: %s, p2: %s, p3: %s", p0, p1, p2, p3)

        # ベジェ曲線の制御点
        s1 = (C + (p1 * 3)) / 3
        s2 = (B - (p1 * 3) + (s1 * 6)) / 3

        bz_x.append(s1.x())
        bz_x.append(s2.x())

        bz_y.append(s1.y())
        bz_y.append(s2.y())

    bz_x.append(xs[-2])
    bz_y.append(ys[-2])

    return bz_x, bz_y
Esempio n. 4
0
    def get_split_fill_fno(self, target_bone_name: str, prev_bf: VmdBoneFrame, next_bf: VmdBoneFrame, \
                           x1_idxs: list, y1_idxs: list, x2_idxs: list, y2_idxs: list):
        next_x1v = next_bf.interpolation[x1_idxs[3]]
        next_y1v = next_bf.interpolation[y1_idxs[3]]
        next_x2v = next_bf.interpolation[x2_idxs[3]]
        next_y2v = next_bf.interpolation[y2_idxs[3]]

        if not MBezierUtils.is_fit_bezier_mmd([MVector2D(), MVector2D(next_x1v, next_y1v), MVector2D(next_x2v, next_y2v), MVector2D()]):
            # ベジェ曲線がMMDの範囲内に収まっていない場合、中点で分割
            new_fill_fno, _, _ = MBezierUtils.evaluate_by_t(next_x1v, next_y1v, next_x2v, next_y2v, prev_bf.fno, next_bf.fno, 0.5)

            if prev_bf.fno < new_fill_fno < next_bf.fno:
                return new_fill_fno
        
        # 範囲内でない場合
        return -1
Esempio n. 5
0
def split_bezier(x1v: int, y1v: int, x2v: int, y2v: int, start: int, now: int,
                 end: int):
    # 補間曲線の進んだ時間分を求める
    x, y, t = evaluate(x1v, y1v, x2v, y2v, start, now, end)

    A = MVector2D(0.0, 0.0)
    B = MVector2D(x1v / INTERPOLATION_MMD_MAX, y1v / INTERPOLATION_MMD_MAX)
    C = MVector2D(x2v / INTERPOLATION_MMD_MAX, y2v / INTERPOLATION_MMD_MAX)
    D = MVector2D(1.0, 1.0)

    E = A * (1 - t) + B * t
    F = B * (1 - t) + C * t
    G = C * (1 - t) + D * t
    H = E * (1 - t) + F * t
    I = F * (1 - t) + G * t  # noqa
    J = H * (1 - t) + I * t

    # 新たな4つのベジェ曲線の制御点は、A側がAEHJ、C側がJIGDとなる。

    # スケーリング
    beforeBz = scale_bezier(A, E, H, J)
    afterBz = scale_bezier(J, I, G, D)

    return x, y, t, beforeBz, afterBz
Esempio n. 6
0
def join_value_2_bezier(fno: int,
                        bone_name: str,
                        values: list,
                        offset=0,
                        diff_limit=0.01):
    if np.isclose(np.max(np.array(values)),
                  np.min(np.array(values)),
                  atol=1e-3) or len(values) <= 2:
        # すべてがだいたい同じ値(最小と最大が同じ値)か次数が1の場合、線形補間
        return LINEAR_MMD_INTERPOLATION

    try:
        # Xは次数(フレーム数)分移動
        xs = np.arange(0, len(values))
        # YはXの移動分を許容範囲とする
        ys = values + xs[-1]

        # カトマル曲線をベジェ曲線に変換する
        bz_x, bz_y = convert_catmullrom_2_bezier(
            np.concatenate([[None], xs, [None]]),
            np.concatenate([[None], ys, [None]]))
        logger.test("bz_x: %s", bz_x)
        logger.test("bz_y: %s", bz_y)

        if len(bz_x) == 0:
            # 始点と終点が指定されていて、カトマル曲線が描けなかった場合、線形補間
            return LINEAR_MMD_INTERPOLATION

        # 次数
        degree = len(bz_x) - 1
        logger.test("degree: %s", degree)

        # すべての制御点を加味したベジェ曲線
        full_curve = bezier.Curve(np.asfortranarray([bz_x, bz_y]),
                                  degree=degree)

        if degree < 3:
            # 3次未満の場合、3次まで次数を増やす
            joined_curve = full_curve.elevate()
            for _ in range(1, 3 - degree):
                joined_curve = joined_curve.elevate()
        elif degree == 3:
            # 3次の場合、そのままベジェ曲線をMMD用に補間
            joined_curve = full_curve
        elif degree > 3:
            # 3次より多い場合、次数を減らす

            reduced_curve_list = []
            bz_x = full_curve.nodes[0]
            bz_y = full_curve.nodes[1]
            logger.test("START bz_x: %s, bz_y: %s", bz_x, bz_y)

            # 3次になるまでベジェ曲線を繋いで減らしていく
            while len(bz_x) > 4:
                reduced_curve_list = []

                for n in range(0, degree + 1, 5):
                    reduce_bz_x = bz_x[n:n + 5]
                    reduce_bz_y = bz_y[n:n + 5]
                    logger.test("n: %s, reduce_bz_x: %s, reduce_bz_y: %s", n,
                                reduce_bz_x, reduce_bz_y)
                    reduced_curve = bezier.Curve(np.asfortranarray(
                        [reduce_bz_x, reduce_bz_y]),
                                                 degree=(len(reduce_bz_x) - 1))

                    # 次数がある場合、減らす
                    if (len(reduce_bz_x) - 1) > 1:
                        reduced_curve = reduced_curve.reduce_()

                    logger.test("n: %s, nodes: %s", n, reduced_curve.nodes)

                    # リストに追加
                    reduced_curve_list.append(reduced_curve)

                bz_x = []
                bz_y = []

                for reduced_curve in reduced_curve_list:
                    bz_x = np.append(bz_x, reduced_curve.nodes[0])
                    bz_y = np.append(bz_y, reduced_curve.nodes[1])

                logger.test("NEXT bz_x: %s, bz_y: %s", bz_x, bz_y)

            logger.test("FINISH bz_x: %s, bz_y: %s", bz_x, bz_y)

            # bz_x = [full_curve.nodes[0][0]] + list(bz_x) + [full_curve.nodes[0][-1]]
            # bz_y = [full_curve.nodes[0][0]] + list(bz_y) + [full_curve.nodes[0][-1]]

            joined_curve = bezier.Curve(np.asfortranarray([bz_x, bz_y]),
                                        degree=(len(bz_x) - 1))

        logger.test("joined_curve: %s", joined_curve.nodes)

        # 全体のキーフレ
        bezier_x = np.arange(0, len(values))[1:-1]

        # 元の2つのベジェ曲線との交点を取得する
        full_ys = intersect_by_x(full_curve, bezier_x)
        logger.test("f: %s, %s, full_ys: %s", fno, bone_name, full_ys)

        # 次数を減らしたベジェ曲線との交点を取得する
        reduced_ys = intersect_by_x(joined_curve, bezier_x)
        logger.test("f: %s, %s, reduced_ys: %s", fno, bone_name, reduced_ys)

        # 交点の差を取得する
        diff_ys = np.array(full_ys) - np.array(reduced_ys)

        # 差が大きい箇所をピックアップする
        diff_large = np.where(
            np.abs(diff_ys) > (diff_limit * (offset + 1)), 1, 0)

        # 差が一定未満である場合、ベジェ曲線をMMD補間曲線に合わせる
        nodes = joined_curve.nodes

        # MMD用補間曲線に変換
        joined_bz = scale_bezier(MVector2D(nodes[0, 0], nodes[1, 0]), MVector2D(nodes[0, 1], nodes[1, 1]), \
                                 MVector2D(nodes[0, 2], nodes[1, 2]), MVector2D(nodes[0, 3], nodes[1, 3]))
        logger.debug("f: %s, %s, values: %s, nodes: %s, full_ys: %s, reduced_ys: %s, diff_ys: %s, diff_limit: %s, diff_large: %s, joined_bz: %s, %s, fit: %s", \
                     fno, bone_name, values, joined_curve.nodes, full_ys, reduced_ys, diff_ys, diff_limit, np.count_nonzero(diff_large) > 0, joined_bz[1], joined_bz[2], \
                     is_fit_bezier_mmd(joined_bz, offset))

        if np.count_nonzero(diff_large) > 0:
            # 差が大きい箇所がある場合、分割不可
            return None

        if not is_fit_bezier_mmd(joined_bz, offset):
            # 補間曲線がMMD補間曲線内に収まらない場合、NG
            return None

        # オフセット込みの場合、MMD用補間曲線枠内に収める
        fit_bezier_mmd(joined_bz)

        # すべてクリアした場合、補間曲線採用
        return joined_bz
    except Exception as e:
        # エラーレベルは落として表に出さない
        logger.debug("ベジェ曲線生成失敗", e)
        return None
Esempio n. 7
0
# -*- coding: utf-8 -*-
#
from module.MMath import MRect, MVector2D, MVector3D, MVector4D, MQuaternion, MMatrix4x4  # noqa
from utils.MLogger import MLogger  # noqa
import numpy as np
import bezier

logger = MLogger(__name__, level=1)

# MMDでの補間曲線の最大値
INTERPOLATION_MMD_MAX = 127
# MMDの線形補間
LINEAR_MMD_INTERPOLATION = [
    MVector2D(0, 0),
    MVector2D(20, 20),
    MVector2D(107, 107),
    MVector2D(127, 127)
]

# 回転補間曲線のインデックス
R_x1_idxs = [3, 18, 33, 48]
R_y1_idxs = [7, 22, 37, 52]
R_x2_idxs = [11, 26, 41, 56]
R_y2_idxs = [15, 30, 45, 60]

# X移動補間曲線のインデックス
MX_x1_idxs = [0, 0, 0, 0]
MX_y1_idxs = [19, 34, 49, 4]
MX_x2_idxs = [23, 38, 53, 8]
MX_y2_idxs = [27, 42, 57, 12]
Esempio n. 8
0
 def test_scale_bezier_point(self):
     v = MBezierUtils.scale_bezier_point(MVector2D(1, 2), MVector2D(3, 4),
                                         MVector2D())
     print("v: %s" % v)
     self.assertAlmostEqual(v.x(), 0, delta=0.1)
     self.assertAlmostEqual(v.y(), 0, delta=0.1)
Esempio n. 9
0
 def test_round_bezier_mmd(self):
     v = MBezierUtils.round_bezier_mmd(MVector2D(0.56, 0))
     print("v: %s" % v)
     self.assertAlmostEqual(v.x(), 71, delta=0.1)
     self.assertAlmostEqual(v.y(), 0, delta=0.1)
Esempio n. 10
0
    def a_test_split_bf_by_fno02(self):
        original_motion = VmdReader(u"test/data/補間曲線テスト01.vmd").read_data()
        model = PmxReader(
            "D:/MMD/MikuMikuDance_v926x64/UserFile/Model/ダミーボーン頂点追加2.pmx"
        ).read_data()

        target_bone_name = "ボーン01"
        links = BoneLinks()
        links.append(model.bones["SIZING_ROOT_BONE"])
        links.append(model.bones["ボーン01"])

        base_params = [0, 16, 32, 127]

        # https://qiita.com/wakame1367/items/0744268e928a28810c20
        for xparams, yparams, zparams, rparams in zip(np.array(np.meshgrid(base_params, base_params, base_params, base_params)).T.reshape(-1, 4), \
                                                      np.array(np.meshgrid(base_params, base_params, base_params, base_params)).T.reshape(-1, 4), \
                                                      np.array(np.meshgrid(base_params, base_params, base_params, base_params)).T.reshape(-1, 4), \
                                                      np.array(np.meshgrid(base_params, base_params, base_params, base_params)).T.reshape(-1, 4)):
            try:
                for fill_fno in range(
                        original_motion.get_bone_fnos(target_bone_name)[0] + 1,
                        original_motion.get_bone_fnos(target_bone_name)[-1]):

                    motion = cPickle.loads(cPickle.dumps(original_motion, -1))

                    # bfの補間曲線を再設定する
                    next_bf = motion.bones[target_bone_name][
                        motion.get_bone_fnos(target_bone_name)[-1]]
                    motion.reset_interpolation_parts(target_bone_name, next_bf, [None, MVector2D(xparams[0], xparams[1]), MVector2D(xparams[2], xparams[3]), None], \
                                                     MBezierUtils.MX_x1_idxs, MBezierUtils.MX_y1_idxs, MBezierUtils.MX_x2_idxs, MBezierUtils.MX_y2_idxs)
                    motion.reset_interpolation_parts(target_bone_name, next_bf, [None, MVector2D(yparams[0], yparams[1]), MVector2D(yparams[2], yparams[3]), None], \
                                                     MBezierUtils.MY_x1_idxs, MBezierUtils.MY_y1_idxs, MBezierUtils.MY_x2_idxs, MBezierUtils.MY_y2_idxs)
                    motion.reset_interpolation_parts(target_bone_name, next_bf, [None, MVector2D(zparams[0], zparams[1]), MVector2D(zparams[2], zparams[3]), None], \
                                                     MBezierUtils.MZ_x1_idxs, MBezierUtils.MZ_y1_idxs, MBezierUtils.MZ_x2_idxs, MBezierUtils.MZ_y2_idxs)
                    motion.reset_interpolation_parts(target_bone_name, next_bf, [None, MVector2D(rparams[0], rparams[1]), MVector2D(rparams[2], rparams[3]), None], \
                                                     MBezierUtils.R_x1_idxs, MBezierUtils.R_y1_idxs, MBezierUtils.R_x2_idxs, MBezierUtils.R_y2_idxs)

                    # 補間曲線を再設定したモーションを再保持
                    org_motion = cPickle.loads(cPickle.dumps(motion, -1))

                    # 間のキーフレをテスト
                    prev_bf = motion.bones[target_bone_name][
                        motion.get_bone_fnos(target_bone_name)[0]]
                    next_bf = motion.bones[target_bone_name][
                        motion.get_bone_fnos(target_bone_name)[-1]]

                    result = motion.split_bf_by_fno(target_bone_name, prev_bf,
                                                    next_bf, fill_fno)
                    # 分割に成功した場合、誤差小。失敗してる場合は誤差大
                    delta = 0.3 if result else 1

                    # print("-----------------------------")

                    # for now_fno in motion.get_bone_fnos(target_bone_name):
                    #     # 有効なキーフレをテスト
                    #     now_bf = motion.calc_bf(target_bone_name, now_fno)

                    #     org_pos_dic = MServiceUtils.calc_global_pos(model, links, org_motion, now_fno)
                    #     now_pos_dic = MServiceUtils.calc_global_pos(model, links, motion, now_fno)

                    #     print("fill_fno: %s, now_fno: %s key: %s ------------" % (fill_fno, now_bf.fno, now_bf.key))
                    #     print("xparams: %s" % xparams)
                    #     print("yparams: %s" % yparams)
                    #     print("zparams: %s" % zparams)
                    #     print("rparams: %s" % rparams)
                    #     print("position: %s" % now_bf.position)
                    #     print("rotation: %s" % now_bf.rotation.toEulerAngles4MMD())
                    #     print("int move x: %s, %s, %s, %s" % (now_bf.interpolation[MBezierUtils.MX_x1_idxs[3]], now_bf.interpolation[MBezierUtils.MX_y1_idxs[3]], \
                    #           now_bf.interpolation[MBezierUtils.MX_x2_idxs[3]], now_bf.interpolation[MBezierUtils.MX_y2_idxs[3]]))
                    #     print("int move y: %s, %s, %s, %s" % (now_bf.interpolation[MBezierUtils.MY_x1_idxs[3]], now_bf.interpolation[MBezierUtils.MY_y1_idxs[3]], \
                    #           now_bf.interpolation[MBezierUtils.MY_x2_idxs[3]], now_bf.interpolation[MBezierUtils.MY_y2_idxs[3]]))
                    #     print("int move z: %s, %s, %s, %s" % (now_bf.interpolation[MBezierUtils.MZ_x1_idxs[3]], now_bf.interpolation[MBezierUtils.MZ_y1_idxs[3]], \
                    #           now_bf.interpolation[MBezierUtils.MZ_x2_idxs[3]], now_bf.interpolation[MBezierUtils.MZ_y2_idxs[3]]))
                    #     print("int rot: %s, %s, %s, %s" % (now_bf.interpolation[MBezierUtils.R_x1_idxs[3]], now_bf.interpolation[MBezierUtils.R_y1_idxs[3]], \
                    #           now_bf.interpolation[MBezierUtils.R_x2_idxs[3]], now_bf.interpolation[MBezierUtils.R_y2_idxs[3]]))

                    #     self.assertAlmostEqual(org_pos_dic[target_bone_name].x(), now_pos_dic[target_bone_name].x(), delta=(delta * 2))
                    #     self.assertAlmostEqual(org_pos_dic[target_bone_name].y(), now_pos_dic[target_bone_name].y(), delta=(delta * 3))
                    #     self.assertAlmostEqual(org_pos_dic[target_bone_name].z(), now_pos_dic[target_bone_name].z(), delta=(delta * 4))

                    print("-----------------------------")

                    for fno in range(
                            motion.get_bone_fnos(target_bone_name)[-1]):
                        # org_bf = org_motion.calc_bf(target_bone_name, fno)
                        now_bf = motion.calc_bf(target_bone_name, fno)

                        org_pos_dic = MServiceUtils.calc_global_pos(
                            model, links, org_motion, fno)
                        now_pos_dic = MServiceUtils.calc_global_pos(
                            model, links, motion, fno)

                        print("** fill_fno: %s, fno: %s key: %s ------------" %
                              (fill_fno, now_bf.fno, now_bf.key))
                        print("xparams: %s" % xparams)
                        print("yparams: %s" % yparams)
                        print("zparams: %s" % zparams)
                        print("rparams: %s" % rparams)
                        print("** position: %s" % now_bf.position)
                        print("** rotation: %s" %
                              now_bf.rotation.toEulerAngles4MMD())
                        print("** int move x: %s, %s, %s, %s" % (now_bf.interpolation[MBezierUtils.MX_x1_idxs[3]], now_bf.interpolation[MBezierUtils.MX_y1_idxs[3]], \
                              now_bf.interpolation[MBezierUtils.MX_x2_idxs[3]], now_bf.interpolation[MBezierUtils.MX_y2_idxs[3]]))
                        print("** int move y: %s, %s, %s, %s" % (now_bf.interpolation[MBezierUtils.MY_x1_idxs[3]], now_bf.interpolation[MBezierUtils.MY_y1_idxs[3]], \
                              now_bf.interpolation[MBezierUtils.MY_x2_idxs[3]], now_bf.interpolation[MBezierUtils.MY_y2_idxs[3]]))
                        print("** int move z: %s, %s, %s, %s" % (now_bf.interpolation[MBezierUtils.MZ_x1_idxs[3]], now_bf.interpolation[MBezierUtils.MZ_y1_idxs[3]], \
                              now_bf.interpolation[MBezierUtils.MZ_x2_idxs[3]], now_bf.interpolation[MBezierUtils.MZ_y2_idxs[3]]))
                        print("** int rot: %s, %s, %s, %s" % (now_bf.interpolation[MBezierUtils.R_x1_idxs[3]], now_bf.interpolation[MBezierUtils.R_y1_idxs[3]], \
                              now_bf.interpolation[MBezierUtils.R_x2_idxs[3]], now_bf.interpolation[MBezierUtils.R_y2_idxs[3]]))

                        self.assertAlmostEqual(
                            org_pos_dic[target_bone_name].x(),
                            now_pos_dic[target_bone_name].x(),
                            delta=(delta * 2))
                        self.assertAlmostEqual(
                            org_pos_dic[target_bone_name].y(),
                            now_pos_dic[target_bone_name].y(),
                            delta=(delta * 3))
                        self.assertAlmostEqual(
                            org_pos_dic[target_bone_name].z(),
                            now_pos_dic[target_bone_name].z(),
                            delta=(delta * 4))

                    # now = datetime.now()

                    # data_set = MOptionsDataSet(motion, model, model, "E:/WebDownload/test_split_bf_by_fno01_{0:%Y%m%d_%H%M%S%f}.vmd".format(now), False, False)
                    # VmdWriter(data_set).write()
                    # print(data_set.output_vmd_path)

                    # data_set = MOptionsDataSet(org_motion, model, model, "E:/WebDownload/test_split_bf_by_fno01_{0:%Y%m%d_%H%M%S%f}_orignal.vmd".format(now), False, False)
                    # VmdWriter(data_set).write()
                    # print(data_set.output_vmd_path)

            except Exception as e:
                # エラーになったらデータを出力する
                now = datetime.now()

                data_set = MOptionsDataSet(
                    motion, model, model,
                    "E:/WebDownload/test_split_bf_by_fno01_{0:%Y%m%d_%H%M%S%f}.vmd"
                    .format(now), False, False)
                VmdWriter(data_set).write()
                print(data_set.output_vmd_path)

                data_set = MOptionsDataSet(
                    org_motion, model, model,
                    "E:/WebDownload/test_split_bf_by_fno01_{0:%Y%m%d_%H%M%S%f}_orignal.vmd"
                    .format(now), False, False)
                VmdWriter(data_set).write()
                print(data_set.output_vmd_path)

                raise e
Esempio n. 11
0
    def test_split_bf_by_fno01(self):
        original_motion = VmdReader(u"test/data/補間曲線テスト01.vmd").read_data()
        model = PmxReader(
            "D:/MMD/MikuMikuDance_v926x64/UserFile/Model/ダミーボーン頂点追加2.pmx"
        ).read_data()

        target_bone_name = "ボーン01"
        links = BoneLinks()
        links.append(model.bones["SIZING_ROOT_BONE"])
        links.append(model.bones["ボーン01"])

        for pidx in range(10):
            try:
                params = np.random.randint(0, 127, (1, 4))
                # params = [[116, 24, 22, 82]]

                for fill_fno in range(
                        original_motion.get_bone_fnos(target_bone_name)[0] + 1,
                        original_motion.get_bone_fnos(target_bone_name)[-1]):

                    motion = original_motion.copy()

                    # bfの補間曲線を再設定する
                    next_bf = motion.bones[target_bone_name][
                        motion.get_bone_fnos(target_bone_name)[-1]]
                    motion.reset_interpolation_parts(target_bone_name, next_bf, [None, MVector2D(20, 20), MVector2D(107, 107), None], \
                                                     MBezierUtils.R_x1_idxs, MBezierUtils.R_y1_idxs, MBezierUtils.R_x2_idxs, MBezierUtils.R_y2_idxs)
                    motion.reset_interpolation_parts(target_bone_name, next_bf, [None, MVector2D(params[0][0], params[0][1]), MVector2D(params[0][2], params[0][3]), None], \
                                                     MBezierUtils.MX_x1_idxs, MBezierUtils.MX_y1_idxs, MBezierUtils.MX_x2_idxs, MBezierUtils.MX_y2_idxs)
                    motion.reset_interpolation_parts(target_bone_name, next_bf, [None, MVector2D(20, 20), MVector2D(107, 107), None], \
                                                     MBezierUtils.MY_x1_idxs, MBezierUtils.MY_y1_idxs, MBezierUtils.MY_x2_idxs, MBezierUtils.MY_y2_idxs)
                    motion.reset_interpolation_parts(target_bone_name, next_bf, [None, MVector2D(20, 20), MVector2D(107, 107), None], \
                                                     MBezierUtils.MZ_x1_idxs, MBezierUtils.MZ_y1_idxs, MBezierUtils.MZ_x2_idxs, MBezierUtils.MZ_y2_idxs)

                    # 補間曲線を再設定したモーションを再保持
                    org_motion = motion.copy()

                    # 間のキーフレをテスト
                    prev_bf = motion.bones[target_bone_name][
                        motion.get_bone_fnos(target_bone_name)[0]]
                    next_bf = motion.bones[target_bone_name][
                        motion.get_bone_fnos(target_bone_name)[-1]]

                    result = motion.split_bf_by_fno(target_bone_name, prev_bf,
                                                    next_bf, fill_fno)
                    # 分割に成功した場合、誤差小。失敗してる場合は誤差大
                    delta = 0.3 if result else 1

                    print("-----------------------------")

                    for now_fno in motion.get_bone_fnos(target_bone_name):
                        # 有効なキーフレをテスト
                        now_bf = motion.calc_bf(target_bone_name, now_fno)

                        org_pos_dic = MServiceUtils.calc_global_pos(
                            model, links, org_motion, now_fno)
                        now_pos_dic = MServiceUtils.calc_global_pos(
                            model, links, motion, now_fno)

                        print(
                            "fill_fno: %s, now_fno: %s key: %s (%s) ------------"
                            % (fill_fno, now_bf.fno, now_bf.key, pidx))
                        print("params: %s" % params)
                        print("position: %s" % now_bf.position)
                        print("rotation: %s" %
                              now_bf.rotation.toEulerAngles4MMD())
                        print("int move x: %s, %s, %s, %s" % (now_bf.interpolation[MBezierUtils.MX_x1_idxs[3]], now_bf.interpolation[MBezierUtils.MX_y1_idxs[3]], \
                              now_bf.interpolation[MBezierUtils.MX_x2_idxs[3]], now_bf.interpolation[MBezierUtils.MX_y2_idxs[3]]))
                        print("int move y: %s, %s, %s, %s" % (now_bf.interpolation[MBezierUtils.MY_x1_idxs[3]], now_bf.interpolation[MBezierUtils.MY_y1_idxs[3]], \
                              now_bf.interpolation[MBezierUtils.MY_x2_idxs[3]], now_bf.interpolation[MBezierUtils.MY_y2_idxs[3]]))
                        print("int move z: %s, %s, %s, %s" % (now_bf.interpolation[MBezierUtils.MZ_x1_idxs[3]], now_bf.interpolation[MBezierUtils.MZ_y1_idxs[3]], \
                              now_bf.interpolation[MBezierUtils.MZ_x2_idxs[3]], now_bf.interpolation[MBezierUtils.MZ_y2_idxs[3]]))
                        print("int rot: %s, %s, %s, %s" % (now_bf.interpolation[MBezierUtils.R_x1_idxs[3]], now_bf.interpolation[MBezierUtils.R_y1_idxs[3]], \
                              now_bf.interpolation[MBezierUtils.R_x2_idxs[3]], now_bf.interpolation[MBezierUtils.R_y2_idxs[3]]))

                        self.assertAlmostEqual(
                            org_pos_dic[target_bone_name].x(),
                            now_pos_dic[target_bone_name].x(),
                            delta=0.2)
                        self.assertAlmostEqual(
                            org_pos_dic[target_bone_name].y(),
                            now_pos_dic[target_bone_name].y(),
                            delta=0.2)
                        self.assertAlmostEqual(
                            org_pos_dic[target_bone_name].z(),
                            now_pos_dic[target_bone_name].z(),
                            delta=0.2)

                    print("-----------------------------")

                    for fno in range(
                            motion.get_bone_fnos(target_bone_name)[-1]):
                        # org_bf = org_motion.calc_bf(target_bone_name, fno)
                        now_bf = motion.calc_bf(target_bone_name, fno)

                        org_pos_dic = MServiceUtils.calc_global_pos(
                            model, links, org_motion, fno)
                        now_pos_dic = MServiceUtils.calc_global_pos(
                            model, links, motion, fno)

                        print(
                            "** fill_fno: %s, fno: %s key: %s (%s) ------------"
                            % (fill_fno, now_bf.fno, now_bf.key, pidx))
                        print("** params: %s" % params)
                        print("** position: %s" % now_bf.position)
                        print("** rotation: %s" %
                              now_bf.rotation.toEulerAngles4MMD())
                        print("** int move x: %s, %s, %s, %s" % (now_bf.interpolation[MBezierUtils.MX_x1_idxs[3]], now_bf.interpolation[MBezierUtils.MX_y1_idxs[3]], \
                              now_bf.interpolation[MBezierUtils.MX_x2_idxs[3]], now_bf.interpolation[MBezierUtils.MX_y2_idxs[3]]))
                        print("** int move y: %s, %s, %s, %s" % (now_bf.interpolation[MBezierUtils.MY_x1_idxs[3]], now_bf.interpolation[MBezierUtils.MY_y1_idxs[3]], \
                              now_bf.interpolation[MBezierUtils.MY_x2_idxs[3]], now_bf.interpolation[MBezierUtils.MY_y2_idxs[3]]))
                        print("** int move z: %s, %s, %s, %s" % (now_bf.interpolation[MBezierUtils.MZ_x1_idxs[3]], now_bf.interpolation[MBezierUtils.MZ_y1_idxs[3]], \
                              now_bf.interpolation[MBezierUtils.MZ_x2_idxs[3]], now_bf.interpolation[MBezierUtils.MZ_y2_idxs[3]]))
                        print("** int rot: %s, %s, %s, %s" % (now_bf.interpolation[MBezierUtils.R_x1_idxs[3]], now_bf.interpolation[MBezierUtils.R_y1_idxs[3]], \
                              now_bf.interpolation[MBezierUtils.R_x2_idxs[3]], now_bf.interpolation[MBezierUtils.R_y2_idxs[3]]))

                        self.assertAlmostEqual(
                            org_pos_dic[target_bone_name].x(),
                            now_pos_dic[target_bone_name].x(),
                            delta=(delta * 2))
                        self.assertAlmostEqual(
                            org_pos_dic[target_bone_name].y(),
                            now_pos_dic[target_bone_name].y(),
                            delta=(delta * 3))
                        self.assertAlmostEqual(
                            org_pos_dic[target_bone_name].z(),
                            now_pos_dic[target_bone_name].z(),
                            delta=(delta * 4))

                    now = datetime.now()

                    data_set = MOptionsDataSet(
                        motion, model, model,
                        "E:/WebDownload/test_split_bf_by_fno01_{0:%Y%m%d_%H%M%S%f}.vmd"
                        .format(now), False, False)
                    VmdWriter(data_set).write()
                    print(data_set.output_vmd_path)

                    data_set = MOptionsDataSet(
                        org_motion, model, model,
                        "E:/WebDownload/test_split_bf_by_fno01_{0:%Y%m%d_%H%M%S%f}_orignal.vmd"
                        .format(now), False, False)
                    VmdWriter(data_set).write()
                    print(data_set.output_vmd_path)

            except Exception as e:
                # エラーになったらデータを出力する
                now = datetime.now()

                data_set = MOptionsDataSet(
                    motion, model, model,
                    "E:/WebDownload/test_split_bf_by_fno01_{0:%Y%m%d_%H%M%S%f}.vmd"
                    .format(now), False, False)
                VmdWriter(data_set).write()
                print(data_set.output_vmd_path)

                data_set = MOptionsDataSet(
                    org_motion, model, model,
                    "E:/WebDownload/test_split_bf_by_fno01_{0:%Y%m%d_%H%M%S%f}_orignal.vmd"
                    .format(now), False, False)
                VmdWriter(data_set).write()
                print(data_set.output_vmd_path)

                raise e