Exemplo n.º 1
0
def calc_direction_qq(bf: VmdBoneFrame, motion: VmdMotion, joints: dict,
                      direction_from_name: str, direction_to_name: str,
                      up_from_name: str, up_to_name: str):
    direction_from_vec = get_vec3(joints["joints"], direction_from_name)
    direction_to_vec = get_vec3(joints["joints"], direction_to_name)
    up_from_vec = get_vec3(joints["joints"], up_from_name)
    up_to_vec = get_vec3(joints["joints"], up_to_name)

    direction = (direction_to_vec - direction_from_vec).normalized()
    up = (up_to_vec - up_from_vec).normalized()
    cross = MVector3D.crossProduct(direction, up)
    qq = MQuaternion.fromDirection(direction, cross)

    return qq
Exemplo n.º 2
0
def calc_bone_direction_qq2(bf: VmdBoneFrame, motion: VmdMotion,
                            model: PmxModel, jname: str,
                            direction_from_name: str, direction_to_name: str,
                            up_from_name: str, up_to_name: str,
                            cross_from_name: str, cross_to_name: str):
    direction_from_vec = get_bone_vec3(model, direction_from_name)
    direction_to_vec = get_bone_vec3(model, direction_to_name)
    up_from_vec = get_bone_vec3(model, up_from_name)
    up_to_vec = get_bone_vec3(model, up_to_name)
    cross_from_vec = get_bone_vec3(model, cross_from_name)
    cross_to_vec = get_bone_vec3(model, cross_to_name)

    direction = (direction_to_vec - direction_from_vec).normalized()
    up = (up_to_vec - up_from_vec).normalized()
    cross = (cross_to_vec - cross_from_vec).normalized()
    qq = MQuaternion.fromDirection(direction,
                                   MVector3D.crossProduct(up, cross))

    return qq
Exemplo n.º 3
0
def execute(cmd_args):
    folder_path = cmd_args.folder_path
    bone_csv_path = cmd_args.bone_csv_path

    model = read_bone_csv(bone_csv_path)
    logger.info(model)

    motion = VmdMotion()

    # 動画上の関節位置
    for fno, joints_path in enumerate(
            glob.glob(osp.join(folder_path, '**/*_joints.json'))):
        logger.info(f"■ fno: {fno} -----")

        frame_joints = {}
        with open(joints_path, 'r') as f:
            frame_joints = json.load(f)

        bf = VmdBoneFrame(fno)
        bf.set_name("センター")
        bf.position = calc_center(frame_joints)
        motion.regist_bf(bf, bf.name, bf.fno)

        for jname, (bone_name, calc_bone, name_list, parent_list,
                    ranges) in VMD_CONNECTIONS.items():
            if name_list is None:
                continue

            bf = VmdBoneFrame(fno)
            bf.set_name(bone_name)

            if calc_bone is None:
                if len(name_list) == 4:
                    rotation = calc_direction_qq(bf.fno, motion, frame_joints,
                                                 *name_list)
                    initial = calc_bone_direction_qq(bf, motion, model, jname,
                                                     *name_list)
                else:
                    rotation = calc_direction_qq2(bf.fno, motion, frame_joints,
                                                  *name_list)
                    initial = calc_bone_direction_qq2(bf, motion, model, jname,
                                                      *name_list)

                qq = MQuaternion()
                for parent_name in reversed(parent_list):
                    qq *= motion.calc_bf(parent_name,
                                         bf.fno).rotation.inverted()
                qq = qq * rotation * initial.inverted()

                if ranges:
                    # 可動域指定がある場合
                    x_qq, y_qq, z_qq, _ = separate_local_qq(
                        bf.fno, bf.name, qq, model.get_local_x_axis(bf.name))
                    local_x_axis = model.get_local_x_axis(bf.name)
                    local_z_axis = MVector3D(
                        0, 0, -1 * (-1 if "right" in jname else 1))
                    local_y_axis = MVector3D.crossProduct(
                        local_x_axis, local_z_axis)
                    x_limited_qq = MQuaternion.fromAxisAndAngle(
                        local_x_axis,
                        max(
                            ranges["x"]["min"],
                            min(
                                ranges["x"]["max"],
                                x_qq.toDegree() * MVector3D.dotProduct(
                                    local_x_axis, x_qq.vector()))))
                    y_limited_qq = MQuaternion.fromAxisAndAngle(
                        local_y_axis,
                        max(
                            ranges["y"]["min"],
                            min(
                                ranges["y"]["max"],
                                y_qq.toDegree() * MVector3D.dotProduct(
                                    local_y_axis, y_qq.vector()))))
                    z_limited_qq = MQuaternion.fromAxisAndAngle(
                        local_z_axis,
                        max(
                            ranges["z"]["min"],
                            min(
                                ranges["z"]["max"],
                                z_qq.toDegree() * MVector3D.dotProduct(
                                    local_z_axis, z_qq.vector()))))
                    bf.rotation = y_limited_qq * x_limited_qq * z_limited_qq
                else:
                    bf.rotation = qq

                motion.regist_bf(bf, bf.name, bf.fno)

    # 動画内の半分は地面に足が着いていると見なす
    center_values = np.zeros((1, 3))
    for bf in motion.bones["センター"].values():
        center_values = np.insert(
            center_values,
            0,
            np.array([bf.position.x(),
                      bf.position.y(),
                      bf.position.z()]),
            axis=0)

    center_median = np.median(center_values, axis=0)

    for bf in motion.bones["センター"].values():
        bf.position.setY(bf.position.y() - center_median[1])

    writer = VmdWriter(
        motion, model,
        osp.join(
            folder_path, "output_{0}.vmd".format(
                datetime.datetime.now().strftime('%Y%m%d_%H%M%S'))))
    writer.write()