Ejemplo n.º 1
0
    def read_data(self):
        # モーションパス
        motion = VmdMotion()
        motion.path = self.file_path

        try:
            with open(self.file_path, "rb") as f:
                # VMDファイルをバイナリ読み込み
                self.buffer = f.read()

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

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

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

                # 1F分のモーション情報

                prev_n = 0
                for n in range(motion.motion_cnt):
                    frame = VmdBoneFrame(0)
                    frame.key = True
                    frame.read = True

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

                    frame.name = bone_name
                    frame.bname = bone_bname
                    logger.test("name: %s, bname %s", bone_name, bone_bname)

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

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

                    # 回転X,Y,Z,scalar
                    frame.rotation = self.read_Quaternion()
                    logger.test("frame.rotation %s", frame.rotation)
                    logger.test("frame.rotation.euler %s",
                                frame.rotation.toEulerAngles())
                    # オリジナルを保持
                    frame.org_rotation = frame.rotation.copy()

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

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

                    # 辞書の該当部分にボーンフレームを追加
                    if frame.fno not in motion.bones[bone_name]:
                        motion.bones[bone_name][frame.fno] = frame

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

                    if n // 10000 > prev_n:
                        prev_n = n // 10000
                        logger.info("-- VMDモーション読み込み キー: %s" % n)

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

                    # 1F分のモーフ情報
                    prev_n = 0
                    for n in range(motion.morph_cnt):
                        morph = VmdMorphFrame()
                        morph.key = True
                        morph.read = True

                        # モーフ ----------------------
                        # モーフ名
                        morph_bname, morph_name = self.read_text(15)

                        morph.name = morph_name
                        morph.bname = morph_bname
                        logger.test("name: %s, bname %s", morph_name,
                                    morph_bname)

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

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

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

                        if morph.fno not in motion.morphs[morph_name]:
                            # まだなければ辞書の該当部分にモーフフレームを追加
                            motion.morphs[morph_name][morph.fno] = morph

                        if n // 1000 > prev_n:
                            prev_n = n // 1000
                            logger.info("-- VMDモーション読み込み モーフ: %s" % n)
                except Exception:
                    # 情報がない場合、catchして握りつぶす
                    motion.morph_cnt = 0

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

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

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

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

                        # 0距離の場合、念のため少しだけ距離を入れておく
                        if camera.length == 0:
                            camera.length = -0.00001

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

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

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

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

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

                        # オリジナルを保持
                        camera.org_length = camera.org_length
                        camera.org_position = camera.org_position.copy()

                        # カメラを追加
                        motion.cameras[camera.fno] = camera

                        if n // 10000 > prev_n:
                            prev_n = n // 10000
                            logger.info("VMDカメラ読み込み キー: %s" % n)

                except Exception:
                    # 情報がない場合、catchして握りつぶす
                    motion.camera_cnt = 0

                # 照明数
                try:
                    motion.light_cnt = self.read_uint(4)
                    logger.test("motion.light_cnt %s", motion.light_cnt)

                    # 1F分の照明情報
                    for _ in range(motion.light_cnt):
                        light = VmdLightFrame()

                        # フレームIDX
                        light.fno = self.read_uint(4)
                        logger.test("light.fno %s", light.fno)

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

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

                        # 追加
                        motion.lights.append(light)

                except Exception:
                    # 情報がない場合、catchして握りつぶす
                    motion.light_cnt = 0

                # セルフシャドウ数
                try:
                    motion.shadow_cnt = self.read_uint(4)
                    logger.test("motion.shadow_cnt %s", motion.shadow_cnt)

                    # 1F分のシャドウ情報
                    for _ in range(motion.shadow_cnt):
                        shadow = VmdShadowFrame()

                        # フレームIDX
                        shadow.fno = self.read_uint(4)
                        logger.test("shadow.fno %s", shadow.fno)

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

                        # 距離
                        shadow.distance = self.read_float()
                        logger.test("shadow.distance %s", shadow.distance)

                        # 追加
                        motion.shadows.append(shadow)

                except Exception:
                    # 情報がない場合、catchして握りつぶす
                    motion.shadow_cnt = 0

                # IK数
                try:
                    motion.ik_cnt = self.read_uint(4)
                    logger.test("motion.ik_cnt %s", motion.ik_cnt)

                    # 1F分のIK情報
                    for _ in range(motion.ik_cnt):
                        show_ik = VmdShowIkFrame()

                        # フレームIDX
                        show_ik.fno = self.read_uint(4)
                        logger.test("ik.fno %s", show_ik.fno)

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

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

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

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

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

                            show_ik.ik.append(ik_info)

                        # 追加
                        motion.showiks.append(show_ik)

                except Exception:
                    # 昔のMMD(MMDv7.39.x64以前)はIK情報がないため、catchして握りつぶす
                    motion.ik_cnt = 0

            # ハッシュを設定
            motion.digest = self.hexdigest()
            logger.test("motion: %s, hash: %s", motion.path, motion.digest)

            return motion
        except MKilledException as ke:
            # 終了命令
            raise ke
        except SizingException as se:
            logger.error("サイジング処理が処理できないデータで終了しました。\n\n%s", se.message)
            return se
        except Exception as e:
            import traceback
            logger.error("サイジング処理が意図せぬエラーで終了しました。\n\n%s",
                         traceback.format_exc())
            raise e
Ejemplo n.º 2
0
    def read_data(self):
        # VPDファイルを通常読み込み
        lines = []

        try:
            with open(self.file_path,
                      "r",
                      encoding=self.get_file_encoding(self.file_path)) as f:
                lines = f.readlines()

            if len(lines) > 0:
                # vpdバージョン
                signature = lines[0]
                logger.test("signature %s", signature)

            motion = VmdMotion()
            # モーション数(常に1)
            motion.motion_cnt = 1
            motion.last_motion_frame = 0

            # 各パターン(括弧はひとつのみ実体として取得する)
            model_name_pattern = re.compile(r'(.*)(?:\.osm;)(?:.*// 親ファイル名.*)',
                                            flags=re.IGNORECASE)
            bone_start_pattern = re.compile(r'(?:.*)(?:{)(.*)',
                                            flags=re.IGNORECASE)
            bone_pos_pattern = re.compile(
                r'([+-]?\d+(?:\.\d+))(?:,)([+-]?\d+(?:\.\d+))(?:,)([+-]?\d+(?:\.\d+))(?:;)(?:.*trans.*)',
                flags=re.IGNORECASE)
            bone_rot_pattern = re.compile(
                r'([+-]?\d+(?:\.\d+))(?:,)([+-]?\d+(?:\.\d+))(?:,)([+-]?\d+(?:\.\d+))(?:,)([+-]?\d+(?:\.\d+))(?:;)(?:.*Quaternion.*)',
                flags=re.IGNORECASE)
            bone_end_pattern = re.compile(r'(?:.*)(})(?:.*)',
                                          flags=re.IGNORECASE)

            frame = None

            for n in range(len(lines)):
                # モデル名
                result_values = self.read_line(lines[n], model_name_pattern, n)
                if result_values:
                    motion.model_name = result_values[0]

                    continue

                # 括弧開始
                result_values = self.read_line(lines[n], bone_start_pattern, n)
                if result_values:
                    bone_name = result_values[0]

                    # キーフレ生成
                    frame = VmdBoneFrame(0)
                    frame.set_name(bone_name)
                    frame.key = True
                    frame.read = True

                    continue

                if frame:
                    # 括弧内のチェック

                    # 位置
                    result_values = self.read_line(lines[n], bone_pos_pattern,
                                                   n)
                    if result_values:
                        # 位置X,Y,Z
                        frame.position = MVector3D(float(result_values[0]),
                                                   float(result_values[1]),
                                                   float(result_values[2]))
                        continue

                    # 角度
                    result_values = self.read_line(lines[n], bone_rot_pattern,
                                                   n)
                    if result_values:
                        # 回転scalar,X,Y,Z
                        frame.rotation = MQuaternion(float(result_values[3]),
                                                     float(result_values[0]),
                                                     float(result_values[1]),
                                                     float(result_values[2]))
                        continue

                    # 括弧終了
                    result_values = self.read_line(lines[n], bone_end_pattern,
                                                   n)
                    if result_values:
                        motion.bones[bone_name] = {0: frame}
                        frame = None
                        continue

            # ハッシュを設定
            motion.digest = self.hexdigest()
            logger.test("motion: %s, hash: %s", motion.path, motion.digest)

            return motion
        except MKilledException as ke:
            # 終了命令
            raise ke
        except SizingException as se:
            logger.error("サイジング処理が処理できないデータで終了しました。\n\n%s", se.message)
            return se
        except Exception as e:
            import traceback
            logger.error("サイジング処理が意図せぬエラーで終了しました。\n\n%s",
                         traceback.print_exc())
            raise e