Esempio n. 1
0
def read_bone_csv(bone_csv_path: str):
    model = PmxModel()
    model.name = osp.splitext(osp.basename(bone_csv_path))[0]

    with open(bone_csv_path, "r",
              encoding=get_file_encoding(bone_csv_path)) as bf:
        reader = csv.reader(bf)

        # 列名行の代わりにルートボーン登録
        # サイジング用ルートボーン
        sizing_root_bone = Bone("SIZING_ROOT_BONE", "SIZING_ROOT_BONE",
                                MVector3D(), -1, 0, 0)
        sizing_root_bone.index = -999

        model.bones[sizing_root_bone.name] = sizing_root_bone
        # インデックス逆引きも登録
        model.bone_indexes[sizing_root_bone.index] = sizing_root_bone.name

        for ridx, row in enumerate(reader):
            if row[0] == "Bone":
                bone = Bone(row[1], row[2], MVector3D(float(row[5]), float(row[6]), float(row[7])), row[13], int(row[3]), \
                            int(row[8]) | int(row[9]) | int(row[10]) | int(row[11]) | int(row[12]))
                bone.index = ridx - 1
                model.bones[row[1]] = bone
                model.bone_indexes[bone.index] = row[1]

    for bidx, bone in model.bones.items():
        # 親ボーンINDEXの設定
        if bone.parent_index and bone.parent_index in model.bones:
            bone.parent_index = model.bones[bone.parent_index].index
        else:
            bone.parent_index = -1

    return model
Esempio n. 2
0
def get_vec3(joints: dict, jname: str):
    if jname in joints:
        joint = joints[jname]
        return MVector3D(joint["x"], joint["y"], joint["z"]) / SCALE_MIKU
    else:
        if jname == "pelvis2":
            # 尾てい骨くらい
            right_hip_vec = get_vec3(joints, "right_hip")
            left_hip_vec = get_vec3(joints, "left_hip")
            return (right_hip_vec + left_hip_vec) / 2

    return MVector3D()
Esempio n. 3
0
def calc_center(frame_joints: dict):
    # プロジェクション座標系の位置
    px = (frame_joints["proj_joints"]["pelvis"]["x"] -
          (frame_joints["image"]["width"] / 2)) * SCALE_MIKU
    py = ((frame_joints["image"]["height"] / 2) -
          frame_joints["proj_joints"]["pelvis"]["y"]) * SCALE_MIKU
    cz = frame_joints["depth"]["depth"] * SCALE_MIKU
    return MVector3D(px, py, cz)
Esempio n. 4
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
Esempio n. 5
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
Esempio n. 6
0
def calc_finger(bf: VmdBoneFrame, motion: VmdMotion, model: PmxModel,
                jname: str, default_joints: dict, frame_joints: dict,
                name_list: list, parent_list: list):
    rotation = calc_direction_qq(bf.fno, motion, frame_joints, *name_list)
    bone_initial = calc_bone_direction_qq(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 * bone_initial.inverted()

    _, _, z_qq, _ = separate_local_qq(bf.fno, bf.name, qq,
                                      model.get_local_x_axis(bf.name))
    z_limited_qq = MQuaternion.fromAxisAndAngle(
        MVector3D(0, 0, -1 * (-1 if "right" in jname else 1)),
        min(90, z_qq.toDegree()))
    bf.rotation = z_limited_qq

    motion.regist_bf(bf, bf.name, bf.fno)
Esempio n. 7
0
def read_bone_csv(bone_csv_path: str):
    model = PmxModel()
    model.name = osp.splitext(osp.basename(bone_csv_path))[0]

    with open(bone_csv_path, "r",
              encoding=get_file_encoding(bone_csv_path)) as f:
        reader = csv.reader(f)

        # 列名行の代わりにルートボーン登録
        # サイジング用ルートボーン
        sizing_root_bone = Bone("SIZING_ROOT_BONE", "SIZING_ROOT_BONE",
                                MVector3D(), -1, 0, 0)
        sizing_root_bone.index = -999

        model.bones[sizing_root_bone.name] = sizing_root_bone
        # インデックス逆引きも登録
        model.bone_indexes[sizing_root_bone.index] = sizing_root_bone.name

        for ridx, row in enumerate(reader):
            if row[0] == "Bone":
                bone = Bone(row[1], row[2], MVector3D(float(row[5]), float(row[6]), float(row[7])), row[13], int(row[3]), \
                            int(row[8]) | int(row[9]) | int(row[10]) | int(row[11]) | int(row[12]))
                bone.index = ridx - 1
                model.bones[row[1]] = bone
                model.bone_indexes[bone.index] = row[1]

    for bidx, bone in model.bones.items():
        # 親ボーンINDEXの設定
        if bone.parent_index and bone.parent_index in model.bones:
            bone.parent_index = model.bones[bone.parent_index].index
        else:
            bone.parent_index = -1

    # 首根元ボーン
    if "左肩" in model.bones and "右肩" in model.bones:
        neck_base_vertex = Vertex(
            -1, (model.bones["左肩"].position + model.bones["右肩"].position) / 2 +
            MVector3D(0, -0.1, 0), MVector3D(), [], [], Vertex.Bdef1(-1), -1)
        neck_base_vertex.position.setX(0)
        neck_base_bone = Bone("首根元", "base of neck",
                              neck_base_vertex.position.copy(), -1, 0, 0)

        if "上半身2" in model.bones:
            # 上半身2がある場合、表示先は、上半身2
            neck_base_bone.parent_index = model.bones["上半身2"].index
            neck_base_bone.tail_index = model.bones["上半身2"].index
        elif "上半身" in model.bones:
            neck_base_bone.parent_index = model.bones["上半身"].index
            neck_base_bone.tail_index = model.bones["上半身"].index

        neck_base_bone.index = len(model.bones.keys())
        model.bones[neck_base_bone.name] = neck_base_bone
        model.bone_indexes[neck_base_bone.index] = neck_base_bone.name

    # 鼻ボーン
    if "頭" in model.bones and "首" in model.bones:
        nose_bone = Bone(
            "鼻", "nose",
            MVector3D(0, model.bones["頭"].position.y(),
                      model.bones["頭"].position.z() - 0.5), -1, 0, 0)
        nose_bone.parent_index = model.bones["首"].index
        nose_bone.tail_index = model.bones["頭"].index
        nose_bone.index = len(model.bones.keys())
        model.bones[nose_bone.name] = nose_bone
        model.bone_indexes[nose_bone.index] = nose_bone.name

    # 頭頂ボーン
    if "頭" in model.bones:
        head_top_bone = Bone(
            "頭頂", "top of head",
            MVector3D(0, model.bones["頭"].position.y() + 1, 0), -1, 0, 0)
        head_top_bone.parent_index = model.bones["鼻"].index
        head_top_bone.index = len(model.bones.keys())
        model.bones[head_top_bone.name] = head_top_bone
        model.bone_indexes[head_top_bone.index] = head_top_bone.name

    if "右つま先" in model.bones:
        right_big_toe_bone = Bone(
            "右足親指", "", model.bones["右つま先"].position + MVector3D(0.5, 0, 0),
            -1, 0, 0)
        right_big_toe_bone.parent_index = model.bones["右足首"].index
        right_big_toe_bone.index = len(model.bones.keys())
        model.bones[right_big_toe_bone.name] = right_big_toe_bone
        model.bone_indexes[right_big_toe_bone.index] = right_big_toe_bone.name

        right_small_toe_bone = Bone(
            "右足小指", "", model.bones["右つま先"].position + MVector3D(-0.5, 0, 0),
            -1, 0, 0)
        right_small_toe_bone.parent_index = model.bones["右足首"].index
        right_small_toe_bone.index = len(model.bones.keys())
        model.bones[right_small_toe_bone.name] = right_small_toe_bone
        model.bone_indexes[
            right_small_toe_bone.index] = right_small_toe_bone.name

    if "左つま先" in model.bones:
        left_big_toe_bone = Bone(
            "左足親指", "", model.bones["左つま先"].position + MVector3D(-0.5, 0, 0),
            -1, 0, 0)
        left_big_toe_bone.parent_index = model.bones["左足首"].index
        left_big_toe_bone.index = len(model.bones.keys())
        model.bones[left_big_toe_bone.name] = left_big_toe_bone
        model.bone_indexes[left_big_toe_bone.index] = left_big_toe_bone.name

        left_small_toe_bone = Bone(
            "左足小指", "", model.bones["左つま先"].position + MVector3D(0.5, 0, 0),
            -1, 0, 0)
        left_small_toe_bone.parent_index = model.bones["左足首"].index
        left_small_toe_bone.index = len(model.bones.keys())
        model.bones[left_small_toe_bone.name] = left_small_toe_bone
        model.bone_indexes[
            left_small_toe_bone.index] = left_small_toe_bone.name

    return model
Esempio n. 8
0
def get_bone_vec3(model: PmxModel, joint_name: str):
    bone_name, _, _, _, _ = VMD_CONNECTIONS[joint_name]
    if bone_name in model.bones:
        return model.bones[bone_name].position

    return MVector3D()
Esempio n. 9
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()