Beispiel #1
0
def create_body_global_3ds(model,
                           motion_frames,
                           body_links,
                           frame,
                           link_names=None):
    # bf生成
    bf = VmdBoneFrame()
    bf.frame = frame

    # 全身のグローバル位置
    # キー:ボーン名、値:ボーングローバル位置
    body_global_3ds = {}

    for limb_links in body_links:
        # 頭と腕のリンクからグローバル位置を算出
        _, _, _, _, global_3ds = utils.create_matrix_global(
            model, limb_links, motion_frames, bf)
        for l, g in zip(reversed(limb_links), global_3ds):
            if link_names is None or (link_names and l.name in link_names):
                # 指定リンク名リストがないか、ある場合、ボーン名がリンク名リストにある場合、登録
                body_global_3ds[l.name] = g

    logger.info("m: %s, frame: %s ---------------------", model.name, frame)
    for k, v in body_global_3ds.items():
        logger.info("%s: %s", k, v)

    return body_global_3ds
Beispiel #2
0
def create_bone_global_3ds(model, motion_frames, body_links, frame, link_names,
                           bone_name, parent_bone_name):
    # bf生成
    bf = VmdBoneFrame()
    bf.frame = frame

    # 指定されたボーンを含むリンクのグローバル位置を算出
    logger.info("replace_model: %s", model.name)
    logger.info("bone_name: %s", bone_name)
    logger.debug("link_names[bone_name]: %s", link_names[bone_name])
    logger.debug("body_links[link_names[bone_name]]: %s",
                 body_links[link_names[bone_name]])
    _, _, _, _, global_3ds = utils.create_matrix_global(
        model, body_links[link_names[bone_name]], motion_frames, bf)

    pgpos = QVector3D()
    for l, g in zip(reversed(body_links[link_names[bone_name]]), global_3ds):
        if l.name == parent_bone_name:
            # 該当親ボーンに相当するグローバル位置を取得
            pgpos = g

        if l.name == bone_name:
            # 該当ボーンに相当するグローバル位置を取得
            logger.info("parent: %s", pgpos)
            logger.info("pos: %s: %s", bone_name, g)
            return g, pgpos

    # 指定されたボーンのグローバル位置が取得できなかった場合
    logger.warn("指定ボーンのグローバル位置取得失敗 %s", bone_name)
    return QVector3D(), QVector3D()
Beispiel #3
0
def position_to_frame_leg_one_side_calc(frame, pos, lower_correctqq,
                                        lower_body_rotation, points,
                                        slope_motion, direction_name):
    # 足
    direction = pos[points['Knee']] - pos[points['Hip']]
    up = QVector3D.crossProduct((pos[points['Knee']] - pos[points['Hip']]),
                                (pos[points['Foot']] - pos[points['Knee']]))
    orientation = QQuaternion.fromDirection(direction, up)
    initial_orientation = QQuaternion.fromDirection(QVector3D(0, -1, 0),
                                                    QVector3D(-1, 0, 0))
    rotation = lower_correctqq * orientation * initial_orientation.inverted()

    # 足の傾きデータ
    leg_correctqq = QQuaternion()
    if slope_motion is not None:
        # Y軸の回転具合を求める
        y_degree = (180 - abs(rotation.toEulerAngles().y())) / 180

        # 一旦オイラー角に変換して、角度のかかり具合を補正し、再度クォータニオンに変換する
        leg_correctqq = QQuaternion.fromEulerAngles(slope_motion.frames[
            "{0}足".format(direction_name)][0].rotation.toEulerAngles() *
                                                    y_degree).inverted()

    leg_rotation = leg_correctqq * lower_body_rotation.inverted() * rotation

    # ひざ
    bf = VmdBoneFrame(frame)
    bf.name = b'\x8d\xb6\x82\xd0\x82\xb4'  # 'ひざ'
    direction = pos[points['Foot']] - pos[points['Knee']]
    up = QVector3D.crossProduct((pos[points['Knee']] - pos[points['Hip']]),
                                (pos[points['Foot']] - pos[points['Knee']]))
    orientation = QQuaternion.fromDirection(direction, up)
    initial_orientation = QQuaternion.fromDirection(QVector3D(0, -1, 0),
                                                    QVector3D(-1, 0, 0))
    rotation = lower_correctqq * orientation * initial_orientation.inverted()

    # ひざの傾きデータ
    knee_correctqq = QQuaternion()
    if slope_motion is not None:
        # Y軸の回転具合を求める
        y_degree = (180 - abs(rotation.toEulerAngles().y())) / 180

        # 一旦オイラー角に変換して、角度のかかり具合を補正し、再度クォータニオンに変換する
        knee_correctqq = QQuaternion.fromEulerAngles(slope_motion.frames[
            "{0}ひざ".format(direction_name)][0].rotation.toEulerAngles() *
                                                     y_degree).inverted()

    knee_rotation = knee_correctqq * leg_rotation.inverted(
    ) * lower_body_rotation.inverted() * rotation

    return leg_rotation, knee_rotation
Beispiel #4
0
    def test_reset_complement_01(self):
        # モーションの宣言
        motion = VmdMotion()
        motion.frames["左手首"] = []

        bf = VmdBoneFrame()
        bf.format_name = "左手首"
        bf.frame = 0
        bf.read = True
        bf.key = True
        bf.complement = [
            10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
            10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
            10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
            10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10
        ]
        motion.frames["左手首"].append(bf)

        # 腕リストの宣言
        arm_links = self.create_arm_links()

        # 処理実施
        sub_arm_ik.reset_complement(motion, arm_links)

        for c in motion.frames["左手首"][0].complement:
            self.assertEqual(10, c)
    # 回転X,Y,Z
    rotation = QQuaternion()

    bone_avg_dic = {}
    # 複数モーションの平均値を求める
    for k, v_list in bone_sum_dic.items():
        for n, v in enumerate(v_list):
            # rotation += v.rotation

            if n == 0:
                rotation = v.rotation
            else:
                # 線形補間で平均を求める
                rotation = QQuaternion.slerp(rotation, v.rotation, 0.5)

        avg_frame = VmdBoneFrame()
        # 名前はキーのをもらう
        avg_frame.name = bone_name_dic[k]
        # 一応正規化
        avg_frame.rotation = rotation.normalized()

        logger.debug("avg name: %s", k)
        logger.debug("avg rotation all: %s", rotation)
        logger.debug("avg rotation: %s", avg_frame.rotation)
        logger.debug("avg rotation all.toEulerAngles(): %s", rotation.toEulerAngles())
        logger.debug("avg rotation.toEulerAngles(): %s", avg_frame.rotation.toEulerAngles())

        bone_avg_dic[k] = avg_frame

    # 平均リスト
    bone_avg_list = []
Beispiel #6
0
def positions_to_frames(pos, vis, frame_num=0, center_enabled=False, head_rotation=None):
    """convert positions to bone frames"""
    frames = []
    if len(pos) < 17:
        return frames

    # センター
    if center_enabled:
        bf = VmdBoneFrame()
        bf.name = b'\x83\x5a\x83\x93\x83\x5e\x81\x5b' # 'センター'
        bf.frame = frame_num
        bf.position = pos[7]
        frames.append(bf)

    # 上半身
    bf = VmdBoneFrame()
    bf.name = b'\x8f\xe3\x94\xbc\x90\x67' # '上半身'
    bf.frame = frame_num
    direction = pos[8] - pos[7]
    up = QVector3D.crossProduct(direction, (pos[14] - pos[11])).normalized()
    upper_body_orientation = QQuaternion.fromDirection(direction, up)
    initial = QQuaternion.fromDirection(QVector3D(0, 1, 0), QVector3D(0, 0, 1))
    bf.rotation = upper_body_orientation * initial.inverted()
    frames.append(bf)
    upper_body_rotation = bf.rotation

    # 下半身
    bf = VmdBoneFrame()
    bf.name = b'\x89\xba\x94\xbc\x90\x67' # '下半身'
    bf.frame = frame_num
    direction = pos[0] - pos[7]
    up = QVector3D.crossProduct(direction, (pos[4] - pos[1]))
    lower_body_orientation = QQuaternion.fromDirection(direction, up)
    initial = QQuaternion.fromDirection(QVector3D(0, -1, 0), QVector3D(0, 0, 1))
    bf.rotation = lower_body_orientation * initial.inverted()
    lower_body_rotation = bf.rotation
    frames.append(bf)

    # 首は回転させず、頭のみ回転させる
    # 頭
    bf = VmdBoneFrame()
    bf.name = b'\x93\xaa' # '頭'
    bf.frame = frame_num
    if head_rotation is None:
        # direction = pos[10] - pos[9]
        direction = pos[10] - pos[8]
        up = QVector3D.crossProduct((pos[9] - pos[8]), (pos[10] - pos[9]))
        orientation = QQuaternion.fromDirection(direction, up)
        initial_orientation = QQuaternion.fromDirection(QVector3D(0, 1, 0), QVector3D(1, 0, 0))
        rotation = orientation * initial_orientation.inverted()
        bf.rotation = upper_body_rotation.inverted() * rotation
    else:
        bf.rotation = upper_body_rotation.inverted() * head_rotation
    frames.append(bf)

    # 左腕
    bf = VmdBoneFrame()
    bf.name = b'\x8d\xb6\x98\x72' # '左腕'
    bf.frame = frame_num
    direction = pos[12] - pos[11]
    up = QVector3D.crossProduct((pos[12] - pos[11]), (pos[13] - pos[12]))
    orientation = QQuaternion.fromDirection(direction, up)
    initial_orientation = QQuaternion.fromDirection(QVector3D(1.73, -1, 0), QVector3D(1, 1.73, 0))
    rotation = orientation * initial_orientation.inverted()
    # 左腕ポーンの回転から親ボーンの回転を差し引いてbf.rotationに格納する。
    # upper_body_rotation * bf.rotation = rotation なので、
    bf.rotation = upper_body_rotation.inverted() * rotation
    left_arm_rotation = bf.rotation # 後で使うので保存しておく
    if vis[6]: # 左ひじが見えているなら
        frames.append(bf)

    # 左ひじ
    bf = VmdBoneFrame()
    bf.name = b'\x8d\xb6\x82\xd0\x82\xb6' # '左ひじ'
    bf.frame = frame_num
    direction = pos[13] - pos[12]
    up = QVector3D.crossProduct((pos[12] - pos[11]), (pos[13] - pos[12]))
    orientation = QQuaternion.fromDirection(direction, up)
    initial_orientation = QQuaternion.fromDirection(QVector3D(1.73, -1, 0), QVector3D(1, 1.73, 0))
    rotation = orientation * initial_orientation.inverted()
    # 左ひじポーンの回転から親ボーンの回転を差し引いてbf.rotationに格納する。
    # upper_body_rotation * left_arm_rotation * bf.rotation = rotation なので、
    bf.rotation = left_arm_rotation.inverted() * upper_body_rotation.inverted() * rotation
    # bf.rotation = (upper_body_rotation * left_arm_rotation).inverted() * rotation # 別の表現
    if vis[6] and vis[7]: # 左ひじと左手首が見えているなら
        frames.append(bf)


    # 右腕
    bf = VmdBoneFrame()
    bf.name = b'\x89\x45\x98\x72' # '右腕'
    bf.frame = frame_num
    direction = pos[15] - pos[14]
    up = QVector3D.crossProduct((pos[15] - pos[14]), (pos[16] - pos[15]))
    orientation = QQuaternion.fromDirection(direction, up)
    initial_orientation = QQuaternion.fromDirection(QVector3D(-1.73, -1, 0), QVector3D(1, -1.73, 0))
    rotation = orientation * initial_orientation.inverted()
    bf.rotation = upper_body_rotation.inverted() * rotation
    right_arm_rotation = bf.rotation
    if vis[3]: # 右ひじが見えているなら
        frames.append(bf)

    # 右ひじ
    bf = VmdBoneFrame()
    bf.name = b'\x89\x45\x82\xd0\x82\xb6' # '右ひじ'
    bf.frame = frame_num
    direction = pos[16] - pos[15]
    up = QVector3D.crossProduct((pos[15] - pos[14]), (pos[16] - pos[15]))
    orientation = QQuaternion.fromDirection(direction, up)
    initial_orientation = QQuaternion.fromDirection(QVector3D(-1.73, -1, 0), QVector3D(1, -1.73, 0))
    rotation = orientation * initial_orientation.inverted()
    bf.rotation = right_arm_rotation.inverted() * upper_body_rotation.inverted() * rotation
    if vis[3] and vis[4]: # 右ひじと右手首が見えているなら
        frames.append(bf)

    # 左足
    bf = VmdBoneFrame()
    bf.name = b'\x8d\xb6\x91\xab' # '左足'
    bf.frame = frame_num
    direction = pos[5] - pos[4]
    up = QVector3D.crossProduct((pos[5] - pos[4]), (pos[6] - pos[5]))
    orientation = QQuaternion.fromDirection(direction, up)
    initial_orientation = QQuaternion.fromDirection(QVector3D(0, -1, 0), QVector3D(-1, 0, 0))
    rotation = orientation * initial_orientation.inverted()
    bf.rotation = lower_body_rotation.inverted() * rotation
    left_leg_rotation = bf.rotation
    if vis[12]: # 左ひざが見えているなら
        frames.append(bf)

    # 左ひざ
    bf = VmdBoneFrame()
    bf.name = b'\x8d\xb6\x82\xd0\x82\xb4' # '左ひざ'
    bf.frame = frame_num
    direction = pos[6] - pos[5]
    up = QVector3D.crossProduct((pos[5] - pos[4]), (pos[6] - pos[5]))
    orientation = QQuaternion.fromDirection(direction, up)
    initial_orientation = QQuaternion.fromDirection(QVector3D(0, -1, 0), QVector3D(-1, 0, 0))
    rotation = orientation * initial_orientation.inverted()
    bf.rotation = left_leg_rotation.inverted() * lower_body_rotation.inverted() * rotation
    if vis[12] and vis[13]: # 左ひざと左足首が見えているなら
        frames.append(bf)

    # 右足
    bf = VmdBoneFrame()
    bf.name = b'\x89\x45\x91\xab' # '右足'
    bf.frame = frame_num
    direction = pos[2] - pos[1]
    up = QVector3D.crossProduct((pos[2] - pos[1]), (pos[3] - pos[2]))
    orientation = QQuaternion.fromDirection(direction, up)
    initial_orientation = QQuaternion.fromDirection(QVector3D(0, -1, 0), QVector3D(-1, 0, 0))
    rotation = orientation * initial_orientation.inverted()
    bf.rotation = lower_body_rotation.inverted() * rotation
    right_leg_rotation = bf.rotation
    if vis[9]: # 右ひざが見えているなら
        frames.append(bf)

    # 右ひざ
    bf = VmdBoneFrame()
    bf.name = b'\x89\x45\x82\xd0\x82\xb4' # '右ひざ'
    bf.frame = frame_num
    direction = pos[3] - pos[2]
    up = QVector3D.crossProduct((pos[2] - pos[1]), (pos[3] - pos[2]))
    orientation = QQuaternion.fromDirection(direction, up)
    initial_orientation = QQuaternion.fromDirection(QVector3D(0, -1, 0), QVector3D(-1, 0, 0))
    rotation = orientation * initial_orientation.inverted()
    bf.rotation = right_leg_rotation.inverted() * lower_body_rotation.inverted() * rotation
    if vis[9] and vis[10]: # 右ひざと右足首が見えているなら
        frames.append(bf)

    return frames
def euler2qq(state, frame=0):

    # 上半身
    bf = VmdBoneFrame(frame)
    bf.name = b'\x8f\xe3\x94\xbc\x90\x67'  # '上半身'
    x, y, z = tuple(state[0])
    bf.rotation = QQuaternion.fromEulerAngles(QVector3D(x, y, z))
    bone_frame_dic["上半身"].append(bf)

    # 下半身
    bf = VmdBoneFrame(frame)
    bf.name = b'\x89\xba\x94\xbc\x90\x67'  # '下半身'
    x, y, z = tuple(state[1])
    bf.rotation = QQuaternion.fromEulerAngles(QVector3D(x, y, z))
    bone_frame_dic["下半身"].append(bf)

    # 首
    bf = VmdBoneFrame(frame)
    bf.name = b'\x8e\xf1'  # '首'
    x, y, z = tuple(state[2])
    bf.rotation = QQuaternion.fromEulerAngles(QVector3D(x, y, z))
    bone_frame_dic["首"].append(bf)

    # 頭
    bf = VmdBoneFrame(frame)
    bf.name = b'\x93\xaa'  # '頭'
    x, y, z = tuple(state[3])
    bf.rotation = QQuaternion.fromEulerAngles(QVector3D(x, y, z))
    bone_frame_dic["頭"].append(bf)

    # 左肩
    bf = VmdBoneFrame(frame)
    bf.name = b'\x8d\xb6\x8C\xA8'  # '左肩'
    x, y, z = tuple(state[4])
    bf.rotation = QQuaternion.fromEulerAngles(QVector3D(x, y, z))
    bone_frame_dic["左肩"].append(bf)

    # 左腕
    bf = VmdBoneFrame(frame)
    bf.name = b'\x8d\xb6\x98\x72'  # '左腕'
    x, y, z = tuple(state[5])
    bf.rotation = QQuaternion.fromEulerAngles(QVector3D(x, y, z))
    bone_frame_dic["左腕"].append(bf)
    rotation_euler = list(bf.rotation.getEulerAngles())

    # 左ひじ
    bf = VmdBoneFrame(frame)
    bf.name = b'\x8d\xb6\x82\xd0\x82\xb6'  # '左ひじ'
    x, y, z = tuple(state[6])
    bf.rotation = QQuaternion.fromEulerAngles(QVector3D(x, y, z))
    bone_frame_dic["左ひじ"].append(bf)

    # 右肩
    bf = VmdBoneFrame(frame)
    bf.name = b'\x89\x45\x8C\xA8'  # '右肩'
    x, y, z = tuple(state[7])
    bf.rotation = QQuaternion.fromEulerAngles(QVector3D(x, y, z))
    bone_frame_dic["右肩"].append(bf)

    # 右腕
    bf = VmdBoneFrame(frame)
    bf.name = b'\x89\x45\x98\x72'  # '右腕'
    x, y, z = tuple(state[8])
    bf.rotation = QQuaternion.fromEulerAngles(QVector3D(x, y, z))
    bone_frame_dic["右腕"].append(bf)

    # 右ひじ
    bf = VmdBoneFrame(frame)
    bf.name = b'\x89\x45\x82\xd0\x82\xb6'  # '右ひじ'
    x, y, z = tuple(state[9])
    bf.rotation = QQuaternion.fromEulerAngles(QVector3D(x, y, z))
    bone_frame_dic["右ひじ"].append(bf)

    # 左足
    bf = VmdBoneFrame(frame)
    bf.name = b'\x8d\xb6\x91\xab'  # '左足'
    bone_frame_dic["左足"].append(bf)

    # 左ひざ
    bf = VmdBoneFrame(frame)
    bf.name = b'\x8d\xb6\x82\xd0\x82\xb4'  # '左ひざ'
    bone_frame_dic["左ひざ"].append(bf)

    # 右足
    bf = VmdBoneFrame(frame)
    bf.name = b'\x89\x45\x91\xab'  # '右足'
    bone_frame_dic["右足"].append(bf)

    # 右ひざ
    bf = VmdBoneFrame(frame)
    bf.name = b'\x89\x45\x82\xd0\x82\xb4'  # '右ひざ'
    bone_frame_dic["右ひざ"].append(bf)

    # センター(箱だけ作る)
    bf = VmdBoneFrame(frame)
    bf.name = b'\x83\x5A\x83\x93\x83\x5E\x81\x5B'  # 'センター'
    bone_frame_dic["センター"].append(bf)

    # グルーブ(箱だけ作る)
    bf = VmdBoneFrame(frame)
    bf.name = b'\x83\x4F\x83\x8B\x81\x5B\x83\x75'  # 'グルーブ'
    bone_frame_dic["グルーブ"].append(bf)

    # 左足IK
    bf = VmdBoneFrame(frame)
    bf.name = b'\x8d\xb6\x91\xab\x82\x68\x82\x6a'  # '左足IK'
    bone_frame_dic["左足IK"].append(bf)

    # 右足IK
    bf = VmdBoneFrame(frame)
    bf.name = b'\x89\x45\x91\xab\x82\x68\x82\x6a'  # '右足IK'
    bone_frame_dic["右足IK"].append(bf)
Beispiel #8
0
    def read_vmd_file(self, filename):
        """Read VMD data to a file"""
        fin = open(filename, "rb").read()
        
        motion = VmdMotion()

        # vmdバージョン
        signature = struct.unpack_from("30s", fin, 0)
        # vmdバージョンは英語だけなので、とりあえずutf-8変換
        motion.signature = byte_decode(signature[0], "utf-8")
        logger.debug("signature %s", motion.signature)

        # モデル名
        model_name = struct.unpack_from("20s", fin, 30)

        # 文字コード
        encoding = get_encoding(model_name[0])

        motion.model_name = byte_decode(model_name[0], encoding)
        logger.debug("model_name %s", motion.model_name)
        
        # モーション数
        motion_cnt = struct.unpack_from("I", fin, 50)
        motion.motion_cnt = motion_cnt[0]
        logger.debug("motion_cnt %s", motion.motion_cnt)

        # 1F分の情報
        for n in range(motion.motion_cnt):
            frame = VmdBoneFrame()
            
            # ボーン名
            bone_bname = struct.unpack_from("15s", fin, 54 + (n * 111))

            # ボーン名はそのまま追加
            frame.name = bone_bname[0]

            # ボーン名を分かる形に変換(キー用)
            bone_name = byte_decode(bone_bname[0], encoding)
            
            logger.debug("frame.name %s", bone_name)

            # フレームIDX
            frame.frame = struct.unpack_from("I", fin, 69 + (n * 111))[0]
            logger.debug("frame.frame %s", frame.frame)

            # 位置X,Y,Z
            frame.position.setX(struct.unpack_from("f", fin, 73 + (n * 111))[0])
            frame.position.setY(struct.unpack_from("f", fin, 77 + (n * 111))[0])
            frame.position.setZ(struct.unpack_from("f", fin, 81 + (n * 111))[0])
            logger.debug("frame.position %s", frame.position)
            
            # 回転X,Y,Z,scalar
            frame.rotation.setX(struct.unpack_from("f", fin, 85 + (n * 111))[0])
            frame.rotation.setY(struct.unpack_from("f", fin, 89 + (n * 111))[0])
            frame.rotation.setZ(struct.unpack_from("f", fin, 93 + (n * 111))[0])
            frame.rotation.setScalar(struct.unpack_from("f", fin, 97 + (n * 111))[0])
            logger.debug("frame.rotation %s", frame.rotation)
            logger.debug("frame.rotation.toEulerAngles() %s", frame.rotation.toEulerAngles())

            # 補間曲線
            frame.complement=['%x' % x for x in range(struct.unpack_from("64B", fin, 101 + (n * 111))[0]) ]
            logger.debug("frame.complement %s", frame.complement)

            if bone_name not in motion.frames:
                # まだ辞書にない場合、配列追加
                motion.frames[bone_name] = []

            # 辞書の該当部分にボーンフレームを追加
            motion.frames[bone_name].append(frame)

        return motion
Beispiel #9
0
def positions_to_frames(pos, frame=0, xangle=0):
    logger.debug("角度計算 frame={0}".format(str(frame)))

	# 補正角度のクォータニオン
    correctqq = QQuaternion.fromEulerAngles(QVector3D(xangle, 0, 0))

    """convert positions to bone frames"""
    # 上半身
    bf = VmdBoneFrame(frame)
    bf.name = b'\x8f\xe3\x94\xbc\x90\x67' # '上半身'
    direction = pos[8] - pos[7]
    up = QVector3D.crossProduct(direction, (pos[14] - pos[11])).normalized()
    upper_body_orientation = QQuaternion.fromDirection(direction, up)
    initial = QQuaternion.fromDirection(QVector3D(0, 1, 0), QVector3D(0, 0, 1))
    # 補正をかけて回転する
    bf.rotation = correctqq * upper_body_orientation * initial.inverted()

    upper_body_rotation = bf.rotation
    bone_frame_dic["上半身"].append(bf)
    
    # 下半身
    bf = VmdBoneFrame(frame)
    bf.name = b'\x89\xba\x94\xbc\x90\x67' # '下半身'
    direction = pos[0] - pos[7]
    up = QVector3D.crossProduct(direction, (pos[4] - pos[1]))
    lower_body_orientation = QQuaternion.fromDirection(direction, up)
    initial = QQuaternion.fromDirection(QVector3D(0, -1, 0), QVector3D(0, 0, 1))
    bf.rotation = correctqq * lower_body_orientation * initial.inverted()
    lower_body_rotation = bf.rotation
    bone_frame_dic["下半身"].append(bf)

    # 首
    bf = VmdBoneFrame(frame)
    bf.name = b'\x8e\xf1' # '首'
    direction = pos[9] - pos[8]
    up = QVector3D.crossProduct((pos[14] - pos[11]), direction).normalized()
    neck_orientation = QQuaternion.fromDirection(up, direction)
    initial_orientation = QQuaternion.fromDirection(QVector3D(0, 0, -1), QVector3D(0, -1, 0))
    rotation = correctqq * neck_orientation * initial_orientation.inverted()
    bf.rotation = upper_body_orientation.inverted() * rotation
    neck_rotation = bf.rotation
    bone_frame_dic["首"].append(bf)

    # 頭
    bf = VmdBoneFrame(frame)
    bf.name = b'\x93\xaa' # '頭'
    direction = pos[10] - pos[9]
    up = QVector3D.crossProduct((pos[9] - pos[8]), (pos[10] - pos[9]))
    orientation = QQuaternion.fromDirection(direction, up)
    initial_orientation = QQuaternion.fromDirection(QVector3D(0, 1, 0), QVector3D(1, 0, 0))
    rotation = correctqq * orientation * initial_orientation.inverted()
    bf.rotation = neck_rotation.inverted() * upper_body_rotation.inverted() * rotation
    bone_frame_dic["頭"].append(bf)
    
    # FIXME 一旦コメントアウト
    # 左肩
    # bf = VmdBoneFrame(frame)
    # bf.name = b'\x8d\xb6\x8C\xA8' # '左肩'
    # direction = pos[11] - pos[8]
    # up = QVector3D.crossProduct((pos[11] - pos[8]), (pos[12] - pos[11]))
    # orientation = QQuaternion.fromDirection(direction, up)
    # # TODO パラメータ要調整
    # initial_orientation = QQuaternion.fromDirection(QVector3D(2, -0.5, 0), QVector3D(0, 0.5, -1.5))
    # rotation = correctqq * orientation * initial_orientation.inverted()
    # # 左肩ポーンの回転から親ボーンの回転を差し引いてbf.rotationに格納する。
    # # upper_body_rotation * bf.rotation = rotation なので、
    # left_shoulder_rotation = upper_body_rotation.inverted() * rotation # 後で使うので保存しておく
    # bf.rotation = left_shoulder_rotation
    # bone_frame_dic["左肩"].append(bf)
    
    # 左腕
    bf = VmdBoneFrame(frame)
    bf.name = b'\x8d\xb6\x98\x72' # '左腕'
    direction = pos[12] - pos[11]
    up = QVector3D.crossProduct((pos[12] - pos[11]), (pos[13] - pos[12]))
    orientation = QQuaternion.fromDirection(direction, up)
    initial_orientation = QQuaternion.fromDirection(QVector3D(1.73, -1, 0), QVector3D(1, 1.73, 0))
    rotation = correctqq * orientation * initial_orientation.inverted()
    # 左腕ポーンの回転から親ボーンの回転を差し引いてbf.rotationに格納する。
    # left_shoulder_rotation * upper_body_rotation * bf.rotation = rotation なので、
    bf.rotation = upper_body_rotation.inverted() * rotation
    left_arm_rotation = bf.rotation # 後で使うので保存しておく
    bone_frame_dic["左腕"].append(bf)
    
    # 左ひじ
    bf = VmdBoneFrame(frame)
    bf.name = b'\x8d\xb6\x82\xd0\x82\xb6' # '左ひじ'
    direction = pos[13] - pos[12]
    up = QVector3D.crossProduct((pos[12] - pos[11]), (pos[13] - pos[12]))
    orientation = QQuaternion.fromDirection(direction, up)
    initial_orientation = QQuaternion.fromDirection(QVector3D(1.73, -1, 0), QVector3D(1, 1.73, 0))
    rotation = orientation * initial_orientation.inverted()
    # ひじはX軸補正しない(Y軸にしか曲がらないから)
    # 左ひじポーンの回転から親ボーンの回転を差し引いてbf.rotationに格納する。
    # upper_body_rotation * left_arm_rotation * bf.rotation = rotation なので、
    bf.rotation = left_arm_rotation.inverted() * upper_body_rotation.inverted() * rotation
    # bf.rotation = (upper_body_rotation * left_arm_rotation).inverted() * rotation # 別の表現
    bone_frame_dic["左ひじ"].append(bf)
    
    # FIXME 一旦コメントアウト
    # 右肩
    # bf = VmdBoneFrame(frame)
    # bf.name = b'\x89\x45\x8C\xA8' # '右肩'
    # direction = pos[14] - pos[8]
    # up = QVector3D.crossProduct((pos[14] - pos[8]), (pos[15] - pos[14]))
    # orientation = QQuaternion.fromDirection(direction, up)
    # # TODO パラメータ要調整
    # initial_orientation = QQuaternion.fromDirection(QVector3D(-2, -0.5, 0), QVector3D(0, 0.5, 1.5))
    # rotation = correctqq * orientation * initial_orientation.inverted()
    # # 左肩ポーンの回転から親ボーンの回転を差し引いてbf.rotationに格納する。
    # # upper_body_rotation * bf.rotation = rotation なので、
    # right_shoulder_rotation = upper_body_rotation.inverted() * rotation # 後で使うので保存しておく
    # bf.rotation = right_shoulder_rotation
    # bone_frame_dic["右肩"].append(bf)
    
    # 右腕
    bf = VmdBoneFrame(frame)
    bf.name = b'\x89\x45\x98\x72' # '右腕'
    direction = pos[15] - pos[14]
    up = QVector3D.crossProduct((pos[15] - pos[14]), (pos[16] - pos[15]))
    orientation = QQuaternion.fromDirection(direction, up)
    initial_orientation = QQuaternion.fromDirection(QVector3D(-1.73, -1, 0), QVector3D(1, -1.73, 0))
    rotation = correctqq * orientation * initial_orientation.inverted()
    bf.rotation = upper_body_rotation.inverted() * rotation
    right_arm_rotation = bf.rotation
    bone_frame_dic["右腕"].append(bf)
    
    # 右ひじ
    bf = VmdBoneFrame(frame)
    bf.name = b'\x89\x45\x82\xd0\x82\xb6' # '右ひじ'
    direction = pos[16] - pos[15]
    up = QVector3D.crossProduct((pos[15] - pos[14]), (pos[16] - pos[15]))
    orientation = QQuaternion.fromDirection(direction, up)
    initial_orientation = QQuaternion.fromDirection(QVector3D(-1.73, -1, 0), QVector3D(1, -1.73, 0))
    # ひじはX軸補正しない(Y軸にしか曲がらないから)
    rotation = orientation * initial_orientation.inverted()
    bf.rotation = right_arm_rotation.inverted() * upper_body_rotation.inverted() * rotation
    bone_frame_dic["右ひじ"].append(bf)

    # 左足
    bf = VmdBoneFrame(frame)
    bf.name = b'\x8d\xb6\x91\xab' # '左足'
    direction = pos[5] - pos[4]
    up = QVector3D.crossProduct((pos[5] - pos[4]), (pos[6] - pos[5]))
    orientation = QQuaternion.fromDirection(direction, up)
    initial_orientation = QQuaternion.fromDirection(QVector3D(0, -1, 0), QVector3D(-1, 0, 0))
    rotation = correctqq * orientation * initial_orientation.inverted()
    bf.rotation = lower_body_rotation.inverted() * rotation
    left_leg_rotation = bf.rotation
    bone_frame_dic["左足"].append(bf)
    
    # 左ひざ
    bf = VmdBoneFrame(frame)
    bf.name = b'\x8d\xb6\x82\xd0\x82\xb4' # '左ひざ'
    direction = pos[6] - pos[5]
    up = QVector3D.crossProduct((pos[5] - pos[4]), (pos[6] - pos[5]))
    orientation = QQuaternion.fromDirection(direction, up)
    initial_orientation = QQuaternion.fromDirection(QVector3D(0, -1, 0), QVector3D(-1, 0, 0))
    rotation = correctqq * orientation * initial_orientation.inverted()
    bf.rotation = left_leg_rotation.inverted() * lower_body_rotation.inverted() * rotation
    bone_frame_dic["左ひざ"].append(bf)

    # 右足
    bf = VmdBoneFrame(frame)
    bf.name = b'\x89\x45\x91\xab' # '右足'
    direction = pos[2] - pos[1]
    up = QVector3D.crossProduct((pos[2] - pos[1]), (pos[3] - pos[2]))
    orientation = QQuaternion.fromDirection(direction, up)
    initial_orientation = QQuaternion.fromDirection(QVector3D(0, -1, 0), QVector3D(-1, 0, 0))
    rotation = correctqq * orientation * initial_orientation.inverted()
    bf.rotation = lower_body_rotation.inverted() * rotation
    right_leg_rotation = bf.rotation
    bone_frame_dic["右足"].append(bf)
    
    # 右ひざ
    bf = VmdBoneFrame(frame)
    bf.name = b'\x89\x45\x82\xd0\x82\xb4' # '右ひざ'
    direction = pos[3] - pos[2]
    up = QVector3D.crossProduct((pos[2] - pos[1]), (pos[3] - pos[2]))
    orientation = QQuaternion.fromDirection(direction, up)
    initial_orientation = QQuaternion.fromDirection(QVector3D(0, -1, 0), QVector3D(-1, 0, 0))
    rotation = correctqq * orientation * initial_orientation.inverted()
    bf.rotation = right_leg_rotation.inverted() * lower_body_rotation.inverted() * rotation
    bone_frame_dic["右ひざ"].append(bf)
    
    # センター(箱だけ作る)
    bf = VmdBoneFrame(frame)
    bf.name = b'\x83\x5A\x83\x93\x83\x5E\x81\x5B' # 'センター'
    bone_frame_dic["センター"].append(bf)
    
    # グルーブ(箱だけ作る)
    bf = VmdBoneFrame(frame)
    bf.name = b'\x83\x4F\x83\x8B\x81\x5B\x83\x75' # 'グルーブ'
    bone_frame_dic["グルーブ"].append(bf)
Beispiel #10
0
def main(csv_bone_path, csv_morph_path, csv_camera_path):

    try:
        bone_frames = []
        morph_frames = []
        camera_frames = []

        if csv_bone_path:
            output_vmd_path = re.sub(
                r'\.csv$', "_{0:%Y%m%d_%H%M%S}.vmd".format(datetime.now()),
                csv_bone_path)

            # ボーンCSV読み込み
            with open(csv_bone_path, encoding='cp932', mode='r') as f:
                reader = csv.reader(f)
                next(reader)  # ヘッダーを読み飛ばす

                for row in reader:
                    bf = VmdBoneFrame()

                    # ボーン名
                    bf.format_name = row[0]

                    # ボーン名(バイト)
                    bf.name = bf.format_name.encode('cp932').decode(
                        'shift_jis').encode('shift_jis')

                    # フレーム
                    bf.frame = int(row[1])

                    # 位置
                    bf.position = QVector3D(float(row[2]), float(row[3]),
                                            float(row[4]))

                    # 回転
                    bf.rotation = QQuaternion.fromEulerAngles(
                        float(row[5]),
                        float(row[6]) * -1,
                        float(row[7]) * -1)

                    # 補間曲線
                    bf.complement = [
                        int(row[8]),
                        int(row[9]),
                        int(row[10]),
                        int(row[11]),
                        int(row[12]),
                        int(row[13]),
                        int(row[14]),
                        int(row[15]),
                        int(row[16]),
                        int(row[17]),
                        int(row[18]),
                        int(row[19]),
                        int(row[20]),
                        int(row[21]),
                        int(row[22]),
                        int(row[23]),
                        int(row[24]),
                        int(row[25]),
                        int(row[26]),
                        int(row[27]),
                        int(row[28]),
                        int(row[29]),
                        int(row[30]),
                        int(row[31]),
                        int(row[32]),
                        int(row[33]),
                        int(row[34]),
                        int(row[35]),
                        int(row[36]),
                        int(row[37]),
                        int(row[38]),
                        int(row[39]),
                        int(row[40]),
                        int(row[41]),
                        int(row[42]),
                        int(row[43]),
                        int(row[44]),
                        int(row[45]),
                        int(row[46]),
                        int(row[47]),
                        int(row[48]),
                        int(row[49]),
                        int(row[50]),
                        int(row[51]),
                        int(row[52]),
                        int(row[53]),
                        int(row[54]),
                        int(row[55]),
                        int(row[56]),
                        int(row[57]),
                        int(row[58]),
                        int(row[59]),
                        int(row[60]),
                        int(row[61]),
                        int(row[62]),
                        int(row[63]),
                        int(row[64]),
                        int(row[65]),
                        int(row[66]),
                        int(row[67]),
                        int(row[68]),
                        int(row[69]),
                        int(row[70]),
                        int(row[71])
                    ]

                    bone_frames.append(bf)

                    # logger.debug("bf: %s %s", bf.name, bf)

        if csv_morph_path:
            output_vmd_path = re.sub(
                r'\.csv$', "_{0:%Y%m%d_%H%M%S}.vmd".format(datetime.now()),
                csv_morph_path)

            # モーフCSV読み込み
            with open(csv_morph_path, encoding='cp932', mode='r') as f:
                reader = csv.reader(f)
                next(reader)  # ヘッダーを読み飛ばす

                for row in reader:
                    mf = VmdMorphFrame()

                    # ボーン名
                    mf.format_name = row[0]

                    # ボーン名(バイト)
                    mf.name = mf.format_name.encode('cp932').decode(
                        'shift_jis').encode('shift_jis')

                    # フレーム
                    mf.frame = int(row[1])

                    # 位置
                    mf.ratio = float(row[2])

                    morph_frames.append(mf)

        writer = VmdWriter()

        if len(morph_frames) > 0 or len(bone_frames) > 0:
            # ボーン・モーフモーション生成
            writer.write_vmd_file(output_vmd_path, "CSV Convert Model",
                                  bone_frames, morph_frames, [], [], [], [])

            print("ボーン・モーフVMD出力成功: %s" % output_vmd_path)

        if csv_camera_path:
            # カメラCSV読み込み
            with open(csv_camera_path, encoding='cp932', mode='r') as f:
                reader = csv.reader(f)
                next(reader)  # ヘッダーを読み飛ばす

                for row in reader:
                    cf = VmdCameraFrame()

                    # フレーム
                    cf.frame = int(row[0])

                    # 位置
                    cf.position = QVector3D(float(row[1]), float(row[2]),
                                            float(row[3]))

                    # 回転(オイラー角)
                    cf.euler = QVector3D(float(row[4]), float(row[5]),
                                         float(row[6]))

                    # 距離
                    cf.length = -(float(row[7]))

                    # 視野角
                    cf.angle = int(row[8])

                    # パース
                    cf.perspective = int(row[9])

                    # 補間曲線
                    cf.complement = [
                        int(row[10]),
                        int(row[11]),
                        int(row[12]),
                        int(row[13]),
                        int(row[14]),
                        int(row[15]),
                        int(row[16]),
                        int(row[17]),
                        int(row[18]),
                        int(row[19]),
                        int(row[20]),
                        int(row[21]),
                        int(row[22]),
                        int(row[23]),
                        int(row[24]),
                        int(row[25]),
                        int(row[26]),
                        int(row[27]),
                        int(row[28]),
                        int(row[29]),
                        int(row[30]),
                        int(row[31]),
                        int(row[32]),
                        int(row[33])
                    ]

                    camera_frames.append(cf)

                    # logger.debug("bf: %s %s", bf.name, bf)

        if len(camera_frames) > 0:
            # カメラモーション生成
            output_vmd_path = re.sub(
                r'\.csv$', "_{0:%Y%m%d_%H%M%S}.vmd".format(datetime.now()),
                csv_camera_path)
            writer.write_vmd_file(output_vmd_path, "CSV Convert Model", [], [],
                                  camera_frames, [], [], [])

            print("カメラVMD出力成功: %s" % output_vmd_path)

    except Exception:
        print("■■■■■■■■■■■■■■■■■")
        print("■ **ERROR** ")
        print("■ CSV解析処理が意図せぬエラーで終了しました。")
        print("■■■■■■■■■■■■■■■■■")

        print(traceback.format_exc())
Beispiel #11
0
def exec(motion, trace_model, replace_model, output_vmd_path,
         org_motion_frames, camera_motion):

    if not camera_motion:
        # カメラモーションが未指定の場合、処理しない
        return True

    if camera_motion.camera_cnt == 0:
        # カメラフレームがなかったら処理しない
        return True

    # 足IKのXYZの比率
    # 横と前後方向の移動はこれと同じ幅に補正されるので。
    xz_ratio, _, _ = sub_move.calc_leg_ik_ratio(trace_model, replace_model)

    # 全身比率、頭身比率、Z比率
    height_ratio, head_ratio, head_z_ratio, org_head_ratio = calc_head_ratio(
        trace_model, replace_model)

    # 情報提供
    # print("カメラ補正: x=%s, y=%s, z=%s + %s 距離=%s" % (xz_ratio, y_ratio, xz_ratio, replace_model.bones[offset_target_bone].offset_z, xz_ratio))
    print("カメラ補正: x=%s, y=%s, z=%s" % (xz_ratio, height_ratio, xz_ratio))
    print("カメラ補正: 全身比率=%s, 頭身比率=%s(%s)" %
          (height_ratio, head_ratio, org_head_ratio))

    # 作成元モデル:全身のリンク
    org_body_links, org_link_names = create_body_links(trace_model)

    # 変換先モデル:全身のリンク
    rep_body_links, rep_link_names = create_body_links(replace_model)

    # 移動縮尺
    prev_cf_pos = None
    is_only_length = False
    for cf_idx, cf in enumerate(camera_motion.cameras):

        logger.debug("cf.frame: %s, l: %s, a: %s", cf.frame, cf.length,
                     cf.angle)
        logger.info("cf.p: %s", cf.position)
        if prev_cf_pos:
            logger.info("prev_cf_pos: %s", prev_cf_pos)
        logger.debug("cf.e: %s", cf.euler)

        org_nearest_bone_name = None
        org_nearest_bone_global_pos = None
        rep_bone_global_pos = None
        org_head_min_boundingbox = None
        org_head_max_boundingbox = None
        rep_head_min_boundingbox = None
        rep_head_max_boundingbox = None

        if cf_idx > 0 and prev_cf_pos is not None and cf.position == prev_cf_pos:
            # 前回と同じカメラ位置の場合、カメラ位置コピー
            logger.info("カメラ位置コピー")
            # 実際にコピーするのは、サイジングした位置情報
            cf.position = copy.deepcopy(camera_motion.cameras[cf_idx -
                                                              1].position)
            is_only_length = True
        else:
            # カメラ位置が変わっている場合、距離以外も調整する
            is_only_length = False

            # 作成元モデルの各ボーングローバル位置
            org_body_global_3ds = create_body_global_3ds(
                trace_model, org_motion_frames, org_body_links, cf.frame,
                rep_link_names)

            # 作成元モデルのどのボーンに最も近いか
            org_nearest_bone_name, org_nearest_bone_global_pos, org_nearest_parent_bone_name, _ = calc_nearest_bone(
                org_body_global_3ds, cf)

            # 作成元モデルの最も近いボーン名と同じボーンの位置を、変換先モデルから取得する
            rep_bone_global_pos, _ = create_bone_global_3ds(
                replace_model, motion.frames, rep_body_links, cf.frame,
                rep_link_names, org_nearest_bone_name,
                org_nearest_parent_bone_name)

            # 直近ボーンが頭付近の場合、頭の頂点を取得
            org_head_min_boundingbox = org_head_max_boundingbox = rep_head_min_boundingbox = rep_head_max_boundingbox = None
            if org_nearest_bone_name in ["首", "頭"]:
                bf = VmdBoneFrame()
                bf.frame = cf.frame

                org_head_min_boundingbox, org_head_max_boundingbox = calc_boundingbox(
                    trace_model, "頭", org_body_links[org_link_names["頭"]],
                    org_motion_frames, bf)
                rep_head_min_boundingbox, rep_head_max_boundingbox = calc_boundingbox(
                    replace_model, "頭", rep_body_links[rep_link_names["頭"]],
                    motion.frames, bf)

        # 前回カメラ位置として保持(カメラ位置変えるので、コピー保持)
        prev_cf_pos = copy.deepcopy(cf.position)

        # 新しいカメラを生成
        create_camera_frame( org_nearest_bone_name, org_nearest_bone_global_pos, rep_bone_global_pos, \
            org_head_min_boundingbox, org_head_max_boundingbox, rep_head_min_boundingbox, rep_head_max_boundingbox, \
            is_only_length, xz_ratio, height_ratio, head_ratio, head_z_ratio, org_head_ratio, cf )

        logger.info("[after] cf.frame: %s", cf.frame)
        logger.info("[after] cf.position: %s", cf.position)
        logger.info("[after] cf.euler: %s", cf.euler)
        logger.info("[after] cf.length: %s", cf.length)

        # if cf.frame > 540:
        #     break

    print("カメラ調整終了")

    return True
def positions_to_frames(pos, head_rotation=None):
    """convert positions to bone frames"""
    frames = []
    # 上半身
    bf = VmdBoneFrame()
    bf.name = b'\x8f\xe3\x94\xbc\x90\x67'  # '上半身'
    direction = pos[8] - pos[7]
    up = QVector3D.crossProduct(direction, (pos[14] - pos[11])).normalized()
    upper_body_orientation = QQuaternion.fromDirection(direction, up)
    initial = QQuaternion.fromDirection(QVector3D(0, 1, 0), QVector3D(0, 0, 1))
    bf.rotation = upper_body_orientation * initial.inverted()
    frames.append(bf)
    upper_body_rotation = bf.rotation

    # 下半身
    bf = VmdBoneFrame()
    bf.name = b'\x89\xba\x94\xbc\x90\x67'  # '下半身'
    direction = pos[0] - pos[7]
    up = QVector3D.crossProduct(direction, (pos[4] - pos[1]))
    lower_body_orientation = QQuaternion.fromDirection(direction, up)
    initial = QQuaternion.fromDirection(QVector3D(0, -1, 0),
                                        QVector3D(0, 0, 1))
    bf.rotation = lower_body_orientation * initial.inverted()
    lower_body_rotation = bf.rotation
    frames.append(bf)

    # 首は回転させず、頭のみ回転させる
    # 頭
    bf = VmdBoneFrame()
    bf.name = b'\x93\xaa'  # '頭'
    if head_rotation is None:
        # direction = pos[10] - pos[9]
        direction = pos[10] - pos[8]
        up = QVector3D.crossProduct((pos[9] - pos[8]), (pos[10] - pos[9]))
        orientation = QQuaternion.fromDirection(direction, up)
        initial_orientation = QQuaternion.fromDirection(
            QVector3D(0, 1, 0), QVector3D(1, 0, 0))
        rotation = orientation * initial_orientation.inverted()
        bf.rotation = upper_body_rotation.inverted() * rotation
    else:
        bf.rotation = upper_body_rotation.inverted() * head_rotation
    frames.append(bf)

    # 左腕
    bf = VmdBoneFrame()
    bf.name = b'\x8d\xb6\x98\x72'  # '左腕'
    direction = pos[12] - pos[11]
    up = QVector3D.crossProduct((pos[12] - pos[11]), (pos[13] - pos[12]))
    orientation = QQuaternion.fromDirection(direction, up)
    initial_orientation = QQuaternion.fromDirection(QVector3D(1.73, -1, 0),
                                                    QVector3D(1, 1.73, 0))
    rotation = orientation * initial_orientation.inverted()
    # 左腕ポーンの回転から親ボーンの回転を差し引いてbf.rotationに格納する。
    # upper_body_rotation * bf.rotation = rotation なので、
    bf.rotation = upper_body_rotation.inverted() * rotation
    left_arm_rotation = bf.rotation  # 後で使うので保存しておく
    frames.append(bf)

    # 左ひじ
    bf = VmdBoneFrame()
    bf.name = b'\x8d\xb6\x82\xd0\x82\xb6'  # '左ひじ'
    direction = pos[13] - pos[12]
    up = QVector3D.crossProduct((pos[12] - pos[11]), (pos[13] - pos[12]))
    orientation = QQuaternion.fromDirection(direction, up)
    initial_orientation = QQuaternion.fromDirection(QVector3D(1.73, -1, 0),
                                                    QVector3D(1, 1.73, 0))
    rotation = orientation * initial_orientation.inverted()
    # 左ひじポーンの回転から親ボーンの回転を差し引いてbf.rotationに格納する。
    # upper_body_rotation * left_arm_rotation * bf.rotation = rotation なので、
    bf.rotation = left_arm_rotation.inverted() * upper_body_rotation.inverted(
    ) * rotation
    # bf.rotation = (upper_body_rotation * left_arm_rotation).inverted() * rotation # 別の表現
    frames.append(bf)

    # 右腕
    bf = VmdBoneFrame()
    bf.name = b'\x89\x45\x98\x72'  # '右腕'
    direction = pos[15] - pos[14]
    up = QVector3D.crossProduct((pos[15] - pos[14]), (pos[16] - pos[15]))
    orientation = QQuaternion.fromDirection(direction, up)
    initial_orientation = QQuaternion.fromDirection(QVector3D(-1.73, -1, 0),
                                                    QVector3D(1, -1.73, 0))
    rotation = orientation * initial_orientation.inverted()
    bf.rotation = upper_body_rotation.inverted() * rotation
    right_arm_rotation = bf.rotation
    frames.append(bf)

    # 右ひじ
    bf = VmdBoneFrame()
    bf.name = b'\x89\x45\x82\xd0\x82\xb6'  # '右ひじ'
    direction = pos[16] - pos[15]
    up = QVector3D.crossProduct((pos[15] - pos[14]), (pos[16] - pos[15]))
    orientation = QQuaternion.fromDirection(direction, up)
    initial_orientation = QQuaternion.fromDirection(QVector3D(-1.73, -1, 0),
                                                    QVector3D(1, -1.73, 0))
    rotation = orientation * initial_orientation.inverted()
    bf.rotation = right_arm_rotation.inverted() * upper_body_rotation.inverted(
    ) * rotation
    frames.append(bf)

    # 左足
    bf = VmdBoneFrame()
    bf.name = b'\x8d\xb6\x91\xab'  # '左足'
    direction = pos[5] - pos[4]
    up = QVector3D.crossProduct((pos[5] - pos[4]), (pos[6] - pos[5]))
    orientation = QQuaternion.fromDirection(direction, up)
    initial_orientation = QQuaternion.fromDirection(QVector3D(0, -1, 0),
                                                    QVector3D(-1, 0, 0))
    rotation = orientation * initial_orientation.inverted()
    bf.rotation = lower_body_rotation.inverted() * rotation
    left_leg_rotation = bf.rotation
    frames.append(bf)

    # 左ひざ
    bf = VmdBoneFrame()
    bf.name = b'\x8d\xb6\x82\xd0\x82\xb4'  # '左ひざ'
    direction = pos[6] - pos[5]
    up = QVector3D.crossProduct((pos[5] - pos[4]), (pos[6] - pos[5]))
    orientation = QQuaternion.fromDirection(direction, up)
    initial_orientation = QQuaternion.fromDirection(QVector3D(0, -1, 0),
                                                    QVector3D(-1, 0, 0))
    rotation = orientation * initial_orientation.inverted()
    bf.rotation = left_leg_rotation.inverted() * lower_body_rotation.inverted(
    ) * rotation
    frames.append(bf)

    # 右足
    bf = VmdBoneFrame()
    bf.name = b'\x89\x45\x91\xab'  # '右足'
    direction = pos[2] - pos[1]
    up = QVector3D.crossProduct((pos[2] - pos[1]), (pos[3] - pos[2]))
    orientation = QQuaternion.fromDirection(direction, up)
    initial_orientation = QQuaternion.fromDirection(QVector3D(0, -1, 0),
                                                    QVector3D(-1, 0, 0))
    rotation = orientation * initial_orientation.inverted()
    bf.rotation = lower_body_rotation.inverted() * rotation
    right_leg_rotation = bf.rotation
    frames.append(bf)

    # 右ひざ
    bf = VmdBoneFrame()
    bf.name = b'\x89\x45\x82\xd0\x82\xb4'  # '右ひざ'
    direction = pos[3] - pos[2]
    up = QVector3D.crossProduct((pos[2] - pos[1]), (pos[3] - pos[2]))
    orientation = QQuaternion.fromDirection(direction, up)
    initial_orientation = QQuaternion.fromDirection(QVector3D(0, -1, 0),
                                                    QVector3D(-1, 0, 0))
    rotation = orientation * initial_orientation.inverted()
    bf.rotation = right_leg_rotation.inverted() * lower_body_rotation.inverted(
    ) * rotation
    frames.append(bf)

    return frames
Beispiel #13
0
    def read_vmd_file(self, filename):
        # VMDファイルをバイナリ読み込み
        self.buffer = open(filename, "rb").read()

        # vmdバージョン
        signature = self.unpack(30, "30s")
        logger.debug("signature %s", signature)

        motion = VmdMotion()

        # モデル名
        model_bname, model_name = self.read_text(20)
        logger.debug("model_bname %s", model_bname)
        motion.model_name = model_name

        # モーション数
        motion.motion_cnt = self.read_uint(4)
        logger.debug("motion.motion_cnt %s", motion.motion_cnt)

        # 1F分のモーション情報
        for _ in range(motion.motion_cnt):
            frame = VmdBoneFrame()

            # ボーン ----------------------
            # ボーン名
            bone_bname, bone_name = self.read_text(15)

            frame.name = bone_bname
            frame.format_name = bone_name
            logger.debug("name: %s, format_name %s", bone_bname, bone_name)

            # フレームIDX
            frame.frame = self.read_uint(4)
            logger.debug("frame.frame %s", frame.frame)

            # 位置X,Y,Z
            frame.position = self.read_Vector3D()
            logger.debug("frame.position %s", frame.position)

            # 回転X,Y,Z,scalar
            frame.rotation = self.read_Quaternion()
            logger.debug("frame.rotation %s", frame.rotation)
            logger.debug("frame.rotation.euler %s",
                         frame.rotation.toEulerAngles())

            # 補間曲線
            frame.complement = self.unpack(64, "64B", True)
            logger.debug("complement %s", frame.complement)

            if bone_name not in motion.frames:
                # まだ辞書にない場合、配列追加
                motion.frames[bone_name] = []

            # 辞書の該当部分にボーンフレームを追加
            motion.frames[bone_name].append(frame)

            if frame.frame > motion.last_motion_frame:
                # 最終フレームを記録
                motion.last_motion_frame = frame.frame

        # ソート
        for k, v in motion.frames.items():
            motion.frames[k] = sorted(v, key=lambda u: u.frame)

        # モーフ数
        motion.morph_cnt = self.read_uint(4)
        logger.debug("motion.morph_cnt %s", motion.morph_cnt)

        # 1F分のモーフ情報
        for _ in range(motion.morph_cnt):
            morph = VmdMorphFrame()

            # ボーン ----------------------
            # ボーン名
            morph_bname, morph_name = self.read_text(15)

            morph.name = morph_bname
            morph.format_name = morph_name
            logger.debug("name: %s, format_name %s", morph_bname, morph_name)

            # フレームIDX
            morph.frame = self.read_uint(4)
            logger.debug("morph.frame %s", morph.frame)

            # 度数
            morph.ratio = self.read_float(4)
            logger.debug("morph.ratio %s", morph.ratio)

            if morph_name not in motion.morphs:
                # まだ辞書にない場合、配列追加
                motion.morphs[morph_name] = []

            # 辞書の該当部分にモーフフレームを追加
            motion.morphs[morph_name].append(morph)

        # ソート
        for k, v in motion.morphs.items():
            motion.morphs[k] = sorted(v, key=lambda u: u.frame)

        # カメラ数
        motion.camera_cnt = self.read_uint(4)
        logger.debug("motion.camera_cnt %s", motion.camera_cnt)

        # 1F分のカメラ情報
        for _ in range(motion.camera_cnt):
            camera = VmdCameraFrame()

            # フレームIDX
            camera.frame = self.read_uint(4)
            logger.debug("camera.frame %s", camera.frame)

            # 距離
            camera.length = self.read_float(4)
            logger.debug("camera.length %s", camera.length)

            # 位置X,Y,Z
            camera.position = self.read_Vector3D()
            logger.debug("camera.position %s", camera.position)

            # 角度(オイラー角)
            camera.euler = self.read_Vector3D()
            logger.debug("camera.euler %s", camera.euler)

            # 補間曲線
            camera.complement = self.unpack(24, "24B", True)
            logger.debug("camera.complement %s", camera.complement)

            # 視野角
            camera.angle = self.read_uint(4)
            logger.debug("camera.angle %s", camera.angle)

            # パース有無
            camera.perspective = self.unpack(1, "B")

            # カメラを追加
            motion.cameras.append(camera)

        # ソート
        motion.cameras = sorted(motion.cameras, key=lambda u: u.frame)

        return motion
Beispiel #14
0
    def read_vmd_file(self, filepath):
        # VMDファイルをバイナリ読み込み
        self.buffer = open(filepath, "rb").read()
        
        # vmdバージョン
        signature = self.unpack(30, "30s")
        logger.debug("signature %s", signature)

        motion = VmdMotion()
        
        # モーションパス
        motion.path = filepath

        # モデル名
        model_bname, model_name = self.read_text(20)
        logger.debug("model_bname %s, model_name: %s", model_bname, model_name)
        motion.model_name = model_name

        # モーション数
        motion.motion_cnt = self.read_uint(4)
        logger.debug("motion.motion_cnt %s", motion.motion_cnt)
        
        # モーションのあるキーのINDEX
        motion_indexes = {}
        
        # 1F分のモーション情報
        for n in range(motion.motion_cnt):
            frame = VmdBoneFrame()
            frame.key = True
            frame.read = True
            
            # ボーン ----------------------
            # ボーン名
            bone_bname, bone_name = self.read_text(15)

            frame.name = bone_bname
            frame.format_name = bone_name
            logger.debug("name: %s, format_name %s", bone_bname, bone_name)
            
            # フレームIDX
            frame.frame = self.read_uint(4)
            logger.debug("frame.frame %s", frame.frame)            
            
            # 位置X,Y,Z
            frame.position = self.read_Vector3D()
            logger.debug("frame.position %s", frame.position)   
            # オリジナルを保持
            frame.org_position = copy.deepcopy(frame.position)         
            
            # 回転X,Y,Z,scalar
            frame.rotation = self.read_Quaternion()
            logger.debug("frame.rotation %s", frame.rotation)            
            logger.debug("frame.rotation.euler %s", frame.rotation.toEulerAngles())            
            # オリジナルを保持
            frame.org_rotation = copy.deepcopy(frame.rotation)         
            
            # 補間曲線
            frame.complement = list(self.unpack(64, "64B", True))
            logger.debug("complement %s", frame.complement)
            # オリジナルの補間曲線を保持しておく
            frame.org_complement = copy.deepcopy(frame.complement)
            logger.debug("org_complement %s", frame.org_complement)
            
            if bone_name not in motion.frames:
                # まだ辞書にない場合、配列追加
                motion.frames[bone_name] = []
                motion_indexes[bone_name] = {}

            is_not_existed = True
            if frame.frame in motion_indexes[bone_name]:
                is_not_existed = False

            # 辞書の該当部分にボーンフレームを追加
            if is_not_existed == True:
                motion.frames[bone_name].append(frame)
                motion_indexes[bone_name][frame.frame] = frame.frame

            if frame.frame > motion.last_motion_frame:
                # 最終フレームを記録
                motion.last_motion_frame = frame.frame
            
            if n % 10000 == 0:
                print("VMDモーション読み込み キー: %s" % n)
                
        # ソート
        for k, v in motion.frames.items():
            motion.frames[k] = sorted(v, key=lambda u: u.frame)

        # モーフ数
        motion.morph_cnt = self.read_uint(4)
        logger.debug("motion.morph_cnt %s", motion.morph_cnt)
                
        # モーションのあるキーのINDEX
        morph_indexes = {}

        # 1F分のモーフ情報
        for n in range(motion.morph_cnt):
            morph = VmdMorphFrame()
            
            # ボーン ----------------------
            # ボーン名
            morph_bname, morph_name = self.read_text(15)

            morph.name = morph_bname
            morph.format_name = morph_name
            logger.debug("name: %s, format_name %s", morph_bname, morph_name)
            
            # フレームIDX
            morph.frame = self.read_uint(4)
            logger.debug("morph.frame %s", morph.frame)            
            
            # 度数
            morph.ratio = self.read_float(4)
            logger.debug("morph.ratio %s", morph.ratio)

            if morph_name not in motion.morphs:
                # まだ辞書にない場合、配列追加
                motion.morphs[morph_name] = []
                morph_indexes[morph_name] = {}

            is_not_existed = True
            if morph.frame in morph_indexes[morph_name]:
                is_not_existed = False

            if is_not_existed == True:
                # まだなければ辞書の該当部分にモーフフレームを追加
                motion.morphs[morph_name].append(morph)
                morph_indexes[morph_name][morph.frame] = morph.frame
        
            if n % 1000 == 0:
                print("VMDモーション読み込み モーフ: %s" % n)
                
        # ソート
        for k, v in motion.morphs.items():
            motion.morphs[k] = sorted(v, key=lambda u: u.frame)

        # カメラ数
        motion.camera_cnt = self.read_uint(4)
        logger.debug("motion.camera_cnt %s", motion.camera_cnt)
        
        # 1F分のカメラ情報
        for _ in range(motion.camera_cnt):
            camera = VmdCameraFrame()
                        
            # フレームIDX
            camera.frame = self.read_uint(4)
            logger.debug("camera.frame %s", camera.frame)            
            
            # 距離
            camera.length = self.read_float(4)
            logger.debug("camera.length %s", camera.length)            
            
            # 位置X,Y,Z
            camera.position = self.read_Vector3D()
            logger.debug("camera.position %s", camera.position)
            
            # 角度(オイラー角)
            camera.euler = self.read_Vector3D()
            logger.debug("camera.euler %s", camera.euler)
            
            # 補間曲線
            camera.complement = self.unpack(24, "24B", True)
            logger.debug("camera.complement %s", camera.complement)
            
            # 視野角
            camera.angle = self.read_uint(4)
            logger.debug("camera.angle %s", camera.angle)
            
            # パース有無
            camera.perspective = self.unpack(1, "B")
            logger.debug("camera.perspective %s", camera.perspective)

            # カメラを追加
            motion.cameras.append(camera)
        
        # ソート
        motion.cameras = sorted(motion.cameras, key=lambda u: u.frame)

        # 照明数
        try:
            motion.light_cnt = self.read_uint(4)
            logger.debug("motion.light_cnt %s", motion.light_cnt)
        except Exception as e:
            # 情報がない場合、catchして握りつぶす
            motion.light_cnt = 0
        
        # 1F分の照明情報
        for _ in range(motion.light_cnt):
            light = VmdLightFrame()
                        
            # フレームIDX
            light.frame = self.read_uint(4)
            logger.debug("light.frame %s", light.frame)     

            # 照明色(RGBだが、下手に数値が変わるのも怖いのでV3D)
            light.color = self.read_Vector3D()
            logger.debug("light.color %s", light.color)            

            # 照明位置
            light.position = self.read_Vector3D()
            logger.debug("light.position %s", light.position) 

            # 追加
            motion.lights.append(light)           
            
        # セルフシャドウ数
        try:
            motion.shadow_cnt = self.read_uint(4)
            logger.debug("motion.shadow_cnt %s", motion.shadow_cnt)

            # 1F分のシャドウ情報
            for _ in range(motion.shadow_cnt):
                shadow = VmdShadowFrame()
                            
                # フレームIDX
                shadow.frame = self.read_uint(4)
                logger.debug("shadow.frame %s", shadow.frame)     

                # シャドウ種別
                shadow.type = self.read_uint(1)
                logger.debug("shadow.type %s", shadow.type)            

                # 距離
                shadow.distance = self.read_float()
                logger.debug("shadow.distance %s", shadow.distance)            
                
                # 追加
                motion.shadows.append(shadow)

        except Exception as e:
            # 情報がない場合、catchして握りつぶす
            motion.shadow_cnt = 0
        
        # IK数
        try:
            motion.ik_cnt = self.read_uint(4)
            logger.debug("motion.ik_cnt %s", motion.ik_cnt)

            # 1F分のIK情報
            for _ in range(motion.ik_cnt):
                ik = VmdShowIkFrame()
                            
                # フレームIDX
                ik.frame = self.read_uint(4)
                logger.debug("ik.frame %s", ik.frame)     

                # モデル表示, 0:OFF, 1:ON
                ik.show = self.read_uint(1)
                logger.debug("ik.show %s", ik.show)            

                # 記録するIKの数
                ik.ik_count = self.read_uint(4)
                logger.debug("ik.ik_count %s", ik.ik_count)     

                for _ in range(ik.ik_count):
                    ik_info = VmdInfoIk()

                    # IK名
                    ik_bname, ik_name = self.read_text(20)
                    ik_info.name = ik_bname
                    logger.debug("ik_info.name %s", ik_name)            

                    # モデル表示, 0:OFF, 1:ON
                    ik_info.onoff = self.read_uint(1)
                    logger.debug("ik_info.onoff %s", ik_info.onoff)            

                    ik.ik.append(ik_info)  

                # 追加
                motion.showiks.append(ik)       
                            
        except Exception as e:
            # 昔のMMD(MMDv7.39.x64以前)はIK情報がないため、catchして握りつぶす
            motion.ik_cnt = 0
        
        # ハッシュを設定
        motion.digest = self.hexdigest(filepath)
        logger.debug("motion: %s, hash: %s", motion.path, motion.digest)

        return motion            
Beispiel #15
0
    def test_reset_complement_06(self):
        # モーションの宣言
        motion = VmdMotion()
        motion.frames["左手首"] = []

        bf = VmdBoneFrame()
        bf.format_name = "左手首"
        bf.frame = 0
        bf.read = True
        bf.key = True
        for r in utils.R_x1_idxs:
            bf.complement[r] = 10
        for r in utils.R_y1_idxs:
            bf.complement[r] = 10
        for r in utils.R_x2_idxs:
            bf.complement[r] = 10
        for r in utils.R_y2_idxs:
            bf.complement[r] = 10
        motion.frames["左手首"].append(bf)

        bf = VmdBoneFrame()
        bf.format_name = "左手首"
        bf.frame = 5
        bf.read = True
        # 間に有効キーあり
        bf.key = True
        for r in utils.R_x1_idxs:
            bf.complement[r] = 30
        for r in utils.R_y1_idxs:
            bf.complement[r] = 30
        for r in utils.R_x2_idxs:
            bf.complement[r] = 30
        for r in utils.R_y2_idxs:
            bf.complement[r] = 30
        motion.frames["左手首"].append(bf)

        bf = VmdBoneFrame()
        bf.format_name = "左手首"
        bf.frame = 10
        bf.read = False
        # 有効キーの次に無効キー
        bf.key = False
        for r in utils.R_x1_idxs:
            bf.complement[r] = 30
        for r in utils.R_y1_idxs:
            bf.complement[r] = 30
        for r in utils.R_x2_idxs:
            bf.complement[r] = 30
        for r in utils.R_y2_idxs:
            bf.complement[r] = 30
        motion.frames["左手首"].append(bf)

        bf = VmdBoneFrame()
        bf.format_name = "左手首"
        bf.frame = 15
        bf.read = False
        # 2つ目の有効キー
        bf.key = True
        for r in utils.R_x1_idxs:
            bf.complement[r] = 30
        for r in utils.R_y1_idxs:
            bf.complement[r] = 30
        for r in utils.R_x2_idxs:
            bf.complement[r] = 30
        for r in utils.R_y2_idxs:
            bf.complement[r] = 30
        motion.frames["左手首"].append(bf)

        bf = VmdBoneFrame()
        bf.format_name = "左手首"
        bf.frame = 30
        bf.read = True
        bf.key = True
        for r in utils.R_x1_idxs:
            bf.complement[r] = 10
        for r in utils.R_y1_idxs:
            bf.complement[r] = 10
        for r in utils.R_x2_idxs:
            bf.complement[r] = 20
        for r in utils.R_y2_idxs:
            bf.complement[r] = 20
        motion.frames["左手首"].append(bf)

        # 腕リストの宣言
        arm_links = self.create_arm_links()

        # 処理実施
        sub_arm_ik.reset_complement(motion, arm_links)

        # ---------------------------------
        # 前回の開始X
        for r in utils.R_x1_idxs:
            self.assertEqual(10, motion.frames["左手首"][0].complement[r])

        # 前回の開始Y
        for r in utils.R_y1_idxs:
            self.assertEqual(10, motion.frames["左手首"][0].complement[r])

        # 前回の終了X
        for r in utils.R_x2_idxs:
            self.assertEqual(10, motion.frames["左手首"][0].complement[r])

        # 前回の終了Y
        for r in utils.R_y2_idxs:
            self.assertEqual(10, motion.frames["左手首"][0].complement[r])

        # ---------------------------------
        # 今回の開始X
        for r in utils.R_x1_idxs:
            self.assertEqual(30, motion.frames["左手首"][1].complement[r])

        # 今回の開始Y
        for r in utils.R_y1_idxs:
            self.assertEqual(30, motion.frames["左手首"][1].complement[r])

        # 今回の終了X
        for r in utils.R_x2_idxs:
            self.assertEqual(30, motion.frames["左手首"][1].complement[r])

        # 今回の終了Y
        for r in utils.R_y2_idxs:
            self.assertEqual(30, motion.frames["左手首"][1].complement[r])

        # ---------------------------------
        # 無効次回の開始X
        for r in utils.R_x1_idxs:
            self.assertEqual(30, motion.frames["左手首"][2].complement[r])

        # 無効次回の開始Y
        for r in utils.R_y1_idxs:
            self.assertEqual(30, motion.frames["左手首"][2].complement[r])

        # 無効次回の終了X
        for r in utils.R_x2_idxs:
            self.assertEqual(30, motion.frames["左手首"][2].complement[r])

        # 無効次回の終了Y
        for r in utils.R_y2_idxs:
            self.assertEqual(30, motion.frames["左手首"][2].complement[r])

        # ---------------------------------
        # 有効次回の開始X
        for r in utils.R_x1_idxs:
            self.assertEqual(17, motion.frames["左手首"][3].complement[r])

        # 有効次回の開始Y
        for r in utils.R_y1_idxs:
            self.assertEqual(17, motion.frames["左手首"][3].complement[r])

        # 有効次回の終了X
        for r in utils.R_x2_idxs:
            self.assertEqual(34, motion.frames["左手首"][3].complement[r])

        # 有効次回の終了Y
        for r in utils.R_y2_idxs:
            self.assertEqual(34, motion.frames["左手首"][3].complement[r])

        # ---------------------------------
        # 次回の開始X
        for r in utils.R_x1_idxs:
            self.assertEqual(29, motion.frames["左手首"][4].complement[r])

        # 次回の開始Y
        for r in utils.R_y1_idxs:
            self.assertEqual(29, motion.frames["左手首"][4].complement[r])

        # 次回の終了X
        for r in utils.R_x2_idxs:
            self.assertEqual(70, motion.frames["左手首"][4].complement[r])

        # 次回の終了Y
        for r in utils.R_y2_idxs:
            self.assertEqual(70, motion.frames["左手首"][4].complement[r])
Beispiel #16
0
def calc_bone_by_complement(frames, bone_name, frameno):
    fillbf = VmdBoneFrame()

    # ボーン登録がなければ初期値
    if bone_name not in frames:
        return fillbf

    for bidx, bf in enumerate(frames[bone_name]):
        if bf.frame >= frameno:
            # 前のキーIDXを0に見立てて、その間の補間曲線を埋める
            fillbf.name = bf.name
            fillbf.frame = frameno
            # 実際に登録はしない
            fillbf.key = False

            # 指定されたフレーム以降
            prev_bf = frames[bone_name][bidx - 1]

            if prev_bf.rotation != bf.rotation:
                # 回転補間曲線
                rn = calc_interpolate_bezier(bf.complement[48],
                                             bf.complement[52],
                                             bf.complement[56],
                                             bf.complement[60], prev_bf.frame,
                                             bf.frame, fillbf.frame)
                fillbf.rotation = QQuaternion.nlerp(prev_bf.rotation,
                                                    bf.rotation, rn)
                # logger.debug("key: %s, n: %s, rn: %s, r: %s ", k, prev_frame + n, rn, QQuaternion.nlerp(prev_bf.rotation, bf.rotation, rn) )
                # logger.debug("rotation: prev: %s, fill: %s ", prev_bf.rotation.toEulerAngles(), fillbf.rotation.toEulerAngles() )
            else:
                fillbf.rotation = copy.deepcopy(prev_bf.rotation)

            # 補間曲線を元に間を埋める
            if prev_bf.position != bf.position:
                # http://rantyen.blog.fc2.com/blog-entry-65.html
                # X移動補間曲線
                xn = calc_interpolate_bezier(bf.complement[0],
                                             bf.complement[4],
                                             bf.complement[8],
                                             bf.complement[12], prev_bf.frame,
                                             bf.frame, fillbf.frame)
                # Y移動補間曲線
                yn = calc_interpolate_bezier(bf.complement[16],
                                             bf.complement[20],
                                             bf.complement[24],
                                             bf.complement[28], prev_bf.frame,
                                             bf.frame, fillbf.frame)
                # Z移動補間曲線
                zn = calc_interpolate_bezier(bf.complement[32],
                                             bf.complement[36],
                                             bf.complement[40],
                                             bf.complement[44], prev_bf.frame,
                                             bf.frame, fillbf.frame)

                fillbf.position.setX(prev_bf.position.x() + (
                    (bf.position.x() - prev_bf.position.x()) * xn))
                fillbf.position.setY(prev_bf.position.y() + (
                    (bf.position.y() - prev_bf.position.y()) * yn))
                fillbf.position.setZ(prev_bf.position.z() + (
                    (bf.position.z() - prev_bf.position.z()) * zn))
                # logger.debug("key: %s, n: %s, xn: %s, yn: %s, zn: %s, xa: %s", k, prev_frame + n, xn, yn, zn, ( bf.position.x() - prev_bf.position.x()) * xn )
                # logger.debug("position: prev: %s, fill: %s ", prev_bf.position, fillbf.position )
            else:
                fillbf.position = copy.deepcopy(prev_bf.position)
                # logger.debug("position stop: %s,%s prev: %s, fill: %s ", prev_frame + n, k, prev_bf.position, bf.position )

            return fillbf

    # 最後まで行っても見つからなければ、最終項目を返す
    return copy.deepcopy(frames[bone_name][-1])
Beispiel #17
0
def position_to_frame(bone_frame_dic, pos, pos_gan, smoothed_2d, frame,
                      is_upper2_body, slope_motion):
    logger.debug("角度計算 frame={0}".format(str(frame)))

    # 体幹の回転
    upper_body_rotation1, upper_body_rotation2, upper_correctqq, lower_body_rotation, lower_correctqq, is_gan \
        = position_to_frame_trunk(bone_frame_dic, frame, pos, pos_gan, is_upper2_body, slope_motion)

    # 上半身
    bf = VmdBoneFrame(frame)
    bf.name = b'\x8f\xe3\x94\xbc\x90\x67'  # '上半身'
    bf.rotation = upper_body_rotation1
    bone_frame_dic["上半身"].append(bf)

    # 上半身2(角度がある場合のみ登録)
    if upper_body_rotation2 != QQuaternion():
        bf = VmdBoneFrame(frame)
        bf.name = b'\x8f\xe3\x94\xbc\x90\x67\x32'  # '上半身2'
        bf.rotation = upper_body_rotation2
        bone_frame_dic["上半身2"].append(bf)

    # 下半身
    bf = VmdBoneFrame(frame)
    bf.name = b'\x89\xba\x94\xbc\x90\x67'  # '下半身'
    bf.rotation = lower_body_rotation
    bone_frame_dic["下半身"].append(bf)

    # 頭の方向の安定化のためNeck/NoseとHeadを20mm前へ動かす(LSld, RSld, Hipでできる平面の垂直方向へ動かす)
    up = QVector3D.crossProduct((pos[0] - pos[14]),
                                (pos[14] - pos[11])).normalized()
    pos[9] += up * 20
    pos[10] += up * 20

    neck_rotation, head_rotation = \
        position_to_frame_head(frame, pos, pos_gan, upper_body_rotation1, upper_body_rotation2, upper_correctqq, is_gan, slope_motion)

    # 首
    bf = VmdBoneFrame(frame)
    bf.name = b'\x8e\xf1'  # '首'
    bf.rotation = neck_rotation
    bone_frame_dic["首"].append(bf)

    # 頭
    bf = VmdBoneFrame(frame)
    bf.name = b'\x93\xaa'  # '頭'
    bf.rotation = head_rotation
    bone_frame_dic["頭"].append(bf)

    # 左肩の初期値
    gan_left_shoulder_initial_orientation = QQuaternion.fromDirection(
        QVector3D(1, 0, 0), QVector3D(0, 1, 0))
    left_shoulder_initial_orientation = QQuaternion.fromDirection(
        QVector3D(2, -0.8, 0), QVector3D(0.5, -0.5, -1))
    left_arm_initial_orientation = QQuaternion.fromDirection(
        QVector3D(1.73, -1, 0), QVector3D(1, 1.73, 0))

    # 左手系の回転
    left_shoulder_rotation, left_arm_rotation, left_elbow_rotation = \
        position_to_frame_arm_one_side(frame, pos, pos_gan, upper_correctqq, upper_body_rotation1, upper_body_rotation2, gan_left_shoulder_initial_orientation, left_shoulder_initial_orientation, left_arm_initial_orientation, LEFT_POINT, is_gan, slope_motion, "左")

    # 左肩
    bf = VmdBoneFrame(frame)
    bf.name = b'\x8d\xb6\x8C\xA8'  # '左肩'
    bf.rotation = left_shoulder_rotation
    bone_frame_dic["左肩"].append(bf)

    # 左腕
    bf = VmdBoneFrame(frame)
    bf.name = b'\x8d\xb6\x98\x72'  # '左腕'
    bf.rotation = left_arm_rotation
    bone_frame_dic["左腕"].append(bf)

    # 左ひじ
    bf = VmdBoneFrame(frame)
    bf.name = b'\x8d\xb6\x82\xd0\x82\xb6'  # '左ひじ'
    bf.rotation = left_elbow_rotation
    bone_frame_dic["左ひじ"].append(bf)

    # 右肩の初期値
    gan_right_shoulder_initial_orientation = QQuaternion.fromDirection(
        QVector3D(-1, 0, 0), QVector3D(0, -1, 0))
    right_shoulder_initial_orientation = QQuaternion.fromDirection(
        QVector3D(-2, -0.8, 0), QVector3D(0.5, 0.5, 1))
    right_arm_initial_orientation = QQuaternion.fromDirection(
        QVector3D(-1.73, -1, 0), QVector3D(1, -1.73, 0))

    # 右手系の回転
    right_shoulder_rotation, right_arm_rotation, right_elbow_rotation = \
        position_to_frame_arm_one_side(frame, pos, pos_gan, upper_correctqq, upper_body_rotation1, upper_body_rotation2, gan_right_shoulder_initial_orientation, right_shoulder_initial_orientation, right_arm_initial_orientation, RIGHT_POINT, is_gan, slope_motion, "右")

    # 右肩
    bf = VmdBoneFrame(frame)
    bf.name = b'\x89\x45\x8C\xA8'  # '右肩'
    bf.rotation = right_shoulder_rotation
    bone_frame_dic["右肩"].append(bf)

    # 右腕
    bf = VmdBoneFrame(frame)
    bf.name = b'\x89\x45\x98\x72'  # '右腕'
    bf.rotation = right_arm_rotation
    bone_frame_dic["右腕"].append(bf)

    # 右ひじ
    bf = VmdBoneFrame(frame)
    bf.name = b'\x89\x45\x82\xd0\x82\xb6'  # '右ひじ'
    bf.rotation = right_elbow_rotation
    bone_frame_dic["右ひじ"].append(bf)

    # 左足と左ひざの回転
    left_leg_rotation, left_knee_rotation = \
        position_to_frame_leg_one_side(frame, pos, pos_gan, lower_correctqq, lower_body_rotation, LEFT_POINT, ["左足", "左ひざ"], is_gan, slope_motion, "左")

    # 膝がまっすぐのときつま先が不自然に回転することがあり、対策のため膝を20mmから100mm前へ移動する
    leg_v = left_leg_rotation.toVector4D()
    leg_x = leg_v.x()
    leg_y = leg_v.y()
    leg_z = leg_v.z()
    leg_w = leg_v.w()
    m20 = 2.0 * leg_x * leg_z + 2.0 * leg_w * leg_y
    m22 = 1.0 - 2.0 * leg_x * leg_x - 2.0 * leg_y * leg_y
    ty = -math.degrees(math.atan2(m20, m22))  # 左脚の角度y
    # RHip, LHip, LFootでできる平面の垂直方向へ移動
    up = QVector3D.crossProduct((pos[6] - pos[4]),
                                (pos[4] - pos[1])).normalized()
    # 左足の回転が大きいほど膝の移動量を増やす(20mmから100mm)
    pos[5] -= up * (20 + 80 * abs(ty) / 180.0)

    # 左足と左ひざの回転の再計算
    left_leg_rotation, left_knee_rotation = \
        position_to_frame_leg_one_side(frame, pos, pos_gan, lower_correctqq, lower_body_rotation, LEFT_POINT, ["左足", "左ひざ"], is_gan, slope_motion, "左")

    # 左足
    bf = VmdBoneFrame(frame)
    bf.name = b'\x8d\xb6\x91\xab'  # '左足'
    bf.rotation = left_leg_rotation
    bone_frame_dic["左足"].append(bf)

    # 左ひざ
    bf = VmdBoneFrame(frame)
    bf.name = b'\x8d\xb6\x82\xd0\x82\xb4'  # '左ひざ'
    bf.rotation = left_knee_rotation
    bone_frame_dic["左ひざ"].append(bf)

    # 右足と右ひざの回転
    right_leg_rotation, right_knee_rotation = \
        position_to_frame_leg_one_side(frame, pos, pos_gan, lower_correctqq, lower_body_rotation, RIGHT_POINT, ["右足", "右ひざ"], is_gan, slope_motion, "右")

    # 膝がまっすぐのときつま先が不自然に回転することがあり、対策のため膝を20mmから100mm前へ移動する
    leg_v = right_leg_rotation.toVector4D()
    leg_x = leg_v.x()
    leg_y = leg_v.y()
    leg_z = leg_v.z()
    leg_w = leg_v.w()
    m20 = 2.0 * leg_x * leg_z + 2.0 * leg_w * leg_y
    m22 = 1.0 - 2.0 * leg_x * leg_x - 2.0 * leg_y * leg_y
    # 右足の角度y
    ty = -math.degrees(math.atan2(m20, m22))
    # LHip, RHip, RFootでできる平面の垂直方向へ移動
    up = QVector3D.crossProduct((pos[3] - pos[1]),
                                (pos[1] - pos[4])).normalized()
    # 右足の回転が大きいほど膝の移動量を増やす(20mmから100mm)
    pos[2] += up * (20 + 80 * abs(ty) / 180.0)

    # 右足と右ひざの回転の再計算
    right_leg_rotation, right_knee_rotation = \
        position_to_frame_leg_one_side(frame, pos, pos_gan, lower_correctqq, lower_body_rotation, RIGHT_POINT, ["右足", "右ひざ"], is_gan, slope_motion, "右")

    # 右足
    bf = VmdBoneFrame(frame)
    bf.name = b'\x89\x45\x91\xab'  # '右足'
    bf.rotation = right_leg_rotation
    bone_frame_dic["右足"].append(bf)

    # 右ひざ
    bf = VmdBoneFrame(frame)
    bf.name = b'\x89\x45\x82\xd0\x82\xb4'  # '右ひざ'
    bf.rotation = right_knee_rotation
    bone_frame_dic["右ひざ"].append(bf)

    # センター(箱だけ作る)
    bf = VmdBoneFrame(frame)
    bf.name = b'\x83\x5A\x83\x93\x83\x5E\x81\x5B'  # 'センター'
    bone_frame_dic["センター"].append(bf)

    # グルーブ(箱だけ作る)
    bf = VmdBoneFrame(frame)
    bf.name = b'\x83\x4F\x83\x8B\x81\x5B\x83\x75'  # 'グルーブ'
    bone_frame_dic["グルーブ"].append(bf)

    # 左足IK
    bf = VmdBoneFrame(frame)
    bf.name = b'\x8d\xb6\x91\xab\x82\x68\x82\x6a'  # '左足IK'
    bone_frame_dic["左足IK"].append(bf)

    # 右足IK
    bf = VmdBoneFrame(frame)
    bf.name = b'\x89\x45\x91\xab\x82\x68\x82\x6a'  # '右足IK'
    bone_frame_dic["右足IK"].append(bf)