예제 #1
0
    def read_float(self, format_size=4):
        if format_size == 4:
            format_type = "f"
        elif format_size == 8:
            format_type = "d"
        else:
            raise ParseException("read_float format_sizeエラー {0}".format(format_size))

        return self.unpack(format_size, format_type)
예제 #2
0
    def read_uint(self, format_size):
        if format_size == 1:
            format_type = "B"
        elif format_size == 2:
            format_type = "H"
        elif format_size == 4:
            format_type = "I"
        else:
            raise ParseException("read_uint format_sizeエラー {0}".format(format_size))

        return self.unpack(format_size, format_type)
예제 #3
0
 def define_read_text(self, text_encoding):
     if text_encoding == 0:
         def read_text():
             format_size = self.read_int(4)
             bresult = self.unpack(format_size, "{0}s".format(format_size))
             return bresult.decode("utf-16-le")
         return read_text
     elif text_encoding == 1:
         def read_text():
             format_size,= self.read_int(4)
             bresult = self.unpack(format_size, "{0}s".format(format_size))
             return bresult.decode("UTF8")
         return read_text
     else:
         raise ParseException("define_read_text 定義エラー {0}".format(text_encoding))
예제 #4
0
 def read_deform(self):
     deform_type = self.read_int(1)
     
     if deform_type == 0:
         # BDEF1
         return PmxModel.Bdef1(self.read_bone_index_size())
     elif deform_type == 1:
         # BDEF2
         return PmxModel.Bdef2(
             self.read_bone_index_size()
             , self.read_bone_index_size()
             , self.read_float()
         )
     elif deform_type == 2:
         # BDEF4
         return PmxModel.Bdef4(
             self.read_bone_index_size()
             , self.read_bone_index_size()
             , self.read_bone_index_size()
             , self.read_bone_index_size()
             , self.read_float()
             , self.read_float()
             , self.read_float()
             , self.read_float()
         )
     elif deform_type == 3:
         # SDEF
         return PmxModel.Sdef(
             self.read_bone_index_size()
             , self.read_bone_index_size()
             , self.read_float()
             , self.read_Vector3D()
             , self.read_Vector3D()
             , self.read_Vector3D()
         )
     elif deform_type == 4:
         # QDEF
         return PmxModel.Qdef(
             self.read_bone_index_size()
             , self.read_bone_index_size()
             , self.read_float()
             , self.read_Vector3D()
             , self.read_Vector3D()
             , self.read_Vector3D()
         )
     else:
         raise ParseException("unknown deform_type: {0}".format(deform_type))
예제 #5
0
    def read_pmx_file(self, filepath):
        # PMXファイルをバイナリ読み込み
        self.buffer = open(filepath, "rb").read()
        # logger.debug("hashlib.algorithms_available: %s", hashlib.algorithms_available)
        
        # pmx宣言
        signature = self.unpack(4, "4s")        
        logger.debug("signature: %s (%s)", signature, self.offset)
        
        # pmxバージョン
        version = self.read_float()        
        logger.debug("version: %s (%s)", version, self.offset)
        
        if signature[:3] != b"PMX" or ( version != 2.0 and version != 2.1 ):
            # 整合性チェック
            raise ParseException("PMX2.0/2.1形式外のデータです。signature: {0}, version: {1} ".format(signature, version))
        
        # flag
        flag_bytes = self.read_int(1)
        logger.debug("flag_bytes: %s (%s)", flag_bytes, self.offset)
        
        # エンコード方式
        text_encoding = self.read_int(1)
        logger.debug("text_encoding: %s (%s)", text_encoding, self.offset)
        # エンコードに基づいて文字列解凍処理を定義
        self.read_text = self.define_read_text(text_encoding)
        
        # 追加UV数
        self.extended_uv = self.read_int(1)
        logger.debug("extended_uv: %s (%s)", self.extended_uv, self.offset)
        
        # 頂点Indexサイズ
        self.vertex_index_size = self.read_int(1)
        logger.debug("vertex_index_size: %s (%s)", self.vertex_index_size, self.offset)
        self.read_vertex_index_size = lambda : self.read_int(self.vertex_index_size)
        
        # テクスチャIndexサイズ
        self.texture_index_size = self.read_int(1)
        logger.debug("texture_index_size: %s (%s)", self.texture_index_size, self.offset)
        self.read_texture_index_size = lambda : self.read_int(self.texture_index_size)
        
        # 材質Indexサイズ
        self.material_index_size = self.read_int(1)
        logger.debug("material_index_size: %s (%s)", self.material_index_size, self.offset)
        self.read_material_index_size = lambda : self.read_int(self.material_index_size)
        
        # ボーンIndexサイズ
        self.bone_index_size = self.read_int(1)
        logger.debug("bone_index_size: %s (%s)", self.bone_index_size, self.offset)
        self.read_bone_index_size = lambda : self.read_int(self.bone_index_size)
        
        # モーフIndexサイズ
        self.morph_index_size = self.read_int(1)
        logger.debug("morph_index_size: %s (%s)", self.morph_index_size, self.offset)
        self.read_morph_index_size = lambda : self.read_int(self.morph_index_size)
        
        # 剛体Indexサイズ
        self.rigidbody_index_size = self.read_int(1)
        logger.debug("rigidbody_index_size: %s (%s)", self.rigidbody_index_size, self.offset)
        self.read_rigidbody_index_size = lambda : self.read_int(self.rigidbody_index_size)
        
        # Pmxモデル生成
        pmx = PmxModel()
        pmx.path = filepath
        
        # モデル名(日本語)
        pmx.name = self.read_text()
        logger.debug("name: %s (%s)", pmx.name, self.offset)
        
        # モデル名(英語)
        pmx.english_name = self.read_text()
        logger.debug("english_name: %s (%s)", pmx.english_name, self.offset)
        
        # コメント(日本語)
        pmx.comment = self.read_text()
        logger.debug("comment: %s (%s)", pmx.comment, self.offset)
        
        # コメント(英語)
        pmx.english_comment = self.read_text()
        logger.debug("english_comment: %s (%s)", pmx.english_comment, self.offset)
        
        # 頂点データリスト
        vidx = 0
        for _ in range(self.read_int(4)):
            position = self.read_Vector3D()
            normal = self.read_Vector3D()
            uv = self.read_Vector2D()

            extended_uvs = []
            if self.extended_uv > 0:
                # 追加UVがある場合
                for _ in range(self.extended_uv):
                    extended_uvs.append(self.read_Vector4D())

            deform = self.read_deform()
            edge_factor = self.read_float()

            vindex = vidx
            vidx += 1

            # 頂点をウェイトボーンごとに分けて保持する
            vertex = pmx.Vertex(vindex, position, normal, uv, extended_uvs, deform, edge_factor)
            for bone_idx in vertex.deform.get_idx_list():
                if not bone_idx in pmx.vertices:
                    pmx.vertices[bone_idx] = []
                pmx.vertices[bone_idx].append(vertex)
                
        logger.debug("len(vertices): %s", len(pmx.vertices))
        logger.debug("vertices.keys: %s", pmx.vertices.keys())

        # 面データリスト
        for _ in range(self.read_int(4)):
            if self.vertex_index_size <= 2:
                # 頂点サイズが2以下の場合、符号なし
                pmx.indices.append(self.read_uint(self.vertex_index_size))
            else:
                pmx.indices.append(self.read_int(self.vertex_index_size))
        logger.debug("len(indices): %s", len(pmx.indices))
                
        # テクスチャデータリスト
        for _ in range(self.read_int(4)):
            pmx.textures.append(self.read_text())
        logger.debug("len(textures): %s", len(pmx.textures))

        # 材質データリスト
        for _ in range(self.read_int(4)):
            material = pmx.Material(
                name = self.read_text(),
                english_name = self.read_text(),
                diffuse_color = self.read_RGB(),
                alpha = self.read_float(),
                specular_color = self.read_RGB(),
                specular_factor = self.read_float(),
                ambient_color = self.read_RGB(),
                flag = self.read_int(1),
                edge_color = self.read_RGBA(),
                edge_size = self.read_float(),
                texture_index = self.read_texture_index_size(),
                sphere_texture_index = self.read_texture_index_size(),
                sphere_mode = self.read_int(1),
                toon_sharing_flag = self.read_int(1)
            )
            
            if material.toon_sharing_flag == 0:
                material.toon_texture_index = self.read_texture_index_size()
            elif material.toon_sharing_flag == 1:
                material.toon_texture_index = self.read_int(1)
            else:
                raise ParseException("unknown toon_sharing_flag {0}".format(material.toon_sharing_flag))
            material.comment = self.read_text()
            material.vertex_count = self.read_int(4)
            
            
            pmx.materials[material.name]  = material
        logger.debug("len(materials): %s", len(pmx.materials))

        # ボーンデータリスト
        for _ in range(self.read_int(4)):
            bone = pmx.Bone(
                name = self.read_text(),
                english_name = self.read_text(),
                position = self.read_Vector3D(),
                parent_index = self.read_bone_index_size(),
                layer = self.read_int(4),
                flag = self.read_int(2)
            )
            
            if not bone.getConnectionFlag():
                bone.tail_position = self.read_Vector3D()
            elif bone.getConnectionFlag():
                bone.tail_index = self.read_bone_index_size()
            else:
                raise ParseException("unknown bone conenction flag: {0}".format(bone.getConnectionFlag()))                

            if bone.getExternalRotationFlag() or bone.getExternalTranslationFlag():
                bone.effect_index = self.read_bone_index_size()
                bone.effect_factor = self.read_float()

            if bone.getFixedAxisFlag():
                bone.fixed_axis = self.read_Vector3D()

            if bone.getLocalCoordinateFlag():
                bone.local_x_vector = self.read_Vector3D()
                bone.local_z_vector = self.read_Vector3D()

            if bone.getExternalParentDeformFlag():
                bone.external_key = self.read_int(4)
                
            if bone.getIkFlag():
                bone.ik = pmx.Ik(
                        target_index = self.read_bone_index_size(),
                        loop = self.read_int(4),
                        limit_radian = self.read_float())
                
                # IKリンク取得
                for _ in range(self.read_int(4)):
                    
                    link = pmx.IkLink(
                            self.read_bone_index_size(),
                            self.read_int(1))
                    
                    if link.limit_angle == 0:
                        pass
                    elif link.limit_angle == 1:
                        link.limit_min = self.read_Vector3D()
                        link.limit_max = self.read_Vector3D()
                    else:
                        raise ParseException("invalid ik link limit_angle: {0}".format(link.limit_angle))
                    
                    bone.ik.link.append(link)

            # ボーンのINDEX
            bone.index = len(pmx.bones.keys())

            pmx.bones[bone.name] = bone
            # インデックス逆引きも登録
            pmx.bone_indexes[bone.index] = bone.name
        
        # 指先ボーンがない場合、代替で挿入
        for direction in ["左", "右"]:
            for (finger_name, end_joint_name) in [("親指", "2"), ("人指", "3"), ("中指", "3"), ("薬指", "3"), ("小指", "3")]:
                end_joint_name = "{0}{1}{2}".format(direction, finger_name, end_joint_name)
                to_joint_name = "{0}{1}{2}".format(direction, finger_name, "先")

                if to_joint_name not in pmx.bones:
                    _, to_pos = self.calc_tail_pos(pmx, end_joint_name)
                    to_bone = pmx.Bone(to_joint_name, None, to_pos, -1, 0, 0)

                    # ボーンのINDEX
                    to_bone.index = len(pmx.bones.keys())
                    pmx.bones[to_bone.name] = to_bone
                    # インデックス逆引きも登録
                    pmx.bone_indexes[to_bone.index] = to_bone.name

        logger.debug("len(bones): %s", len(pmx.bones))
        
        # ボーンの長さを計算する
        self.calc_bone_length(pmx.bones, pmx.bone_indexes)

        # 操作パネル (PMD:カテゴリ) 1:眉(左下) 2:目(左上) 3:口(右上) 4:その他(右下)
        morphs_by_panel = OrderedDict()
        morphs_by_panel[2] = [] # 目
        morphs_by_panel[1] = [] # 眉
        morphs_by_panel[3] = [] # 口
        morphs_by_panel[4] = [] # 他
        morphs_by_panel[0] = [] # システム予約

        morph_idx = 0
        # モーフデータリスト
        for _ in range(self.read_int(4)):      
            morph = PmxModel.Morph(
                name = self.read_text(),
                english_name = self.read_text(),
                panel=self.read_int(1),
                morph_type=self.read_int(1)
            )

            offset_size=self.read_int(4)

            if morph.morph_type==0:
                # group
                morph.offsets=[self.read_group_morph_data() for _ in range(offset_size)]
            elif morph.morph_type==1:
                # vertex
                morph.offsets=[self.read_vertex_position_morph_offset() for _ in range(offset_size)]
            elif morph.morph_type==2:
                # bone
                morph.offsets=[self.read_bone_morph_data() for _ in range(offset_size)]
            elif morph.morph_type==3:
                # uv
                morph.offsets=[self.read_uv_morph_data() for _ in range(offset_size)]
            elif morph.morph_type==4:
                # uv extended1
                morph.offsets=[self.read_uv_morph_data() for _ in range(offset_size)]
            elif morph.morph_type==5:
                # uv extended2
                morph.offsets=[self.read_uv_morph_data() for _ in range(offset_size)]
            elif morph.morph_type==6:
                # uv extended3
                morph.offsets=[self.read_uv_morph_data() for _ in range(offset_size)]
            elif morph.morph_type==7:
                # uv extended4
                morph.offsets=[self.read_uv_morph_data() for _ in range(offset_size)]
            elif morph.morph_type==8:
                # material
                morph.data=[self.read_material_morph_data() for _ in range(offset_size)]
            else:
                raise ParseException("unknown morph type: {0}".format(morph.morph_type))

            # モーフのINDEXは、先頭から順番に設定
            morph.index = morph_idx
            morph_idx += 1

            if not morph.panel in morphs_by_panel.keys():
                # ないと思うが念のためパネル情報がなければ追加
                morphs_by_panel[morph.panel] = 0

            morphs_by_panel[morph.panel].append(morph)

        # モーフのパネル順に並び替えてモーフを登録していく
        for _, mlist in morphs_by_panel.items():
            for m in mlist:
                pmx.morphs[m.name] = m

        logger.debug("len(morphs): %s", len(pmx.morphs))

        # 表示枠データリスト
        for _ in range(self.read_int(4)):      
            display_slot = PmxModel.DisplaySlot(
                name = self.read_text(),
                english_name = self.read_text(),
                special_flag=self.read_int(1)
            )

            display_count=self.read_int(4)

            for _ in range(display_count):
                display_type=self.read_int(1)
                if display_type==0:
                    born_idx = self.read_bone_index_size()
                    display_slot.references.append((display_type, born_idx))
                    # ボーン表示ON
                    for v in pmx.bones.values():
                        if v.index == born_idx:
                            v.display = True
                elif display_type==1:
                    morph_idx = self.read_morph_index_size()
                    display_slot.references.append((display_type, morph_idx))
                    # モーフ表示ON
                    for v in pmx.morphs.values():
                        if v.index == morph_idx:
                            v.display = True
                        # logger.debug("v: %s, display: %s", v.name, v.display)
                else:
                    raise ParseException("unknown display_type: {0}".format(display_type))

            pmx.display_slots[display_slot.name] = display_slot

        logger.debug("len(display_slots): %s", len(pmx.display_slots))

        # 剛体データリスト
        for _ in range(self.read_int(4)):      
            rigidbody = PmxModel.RigidBody(
                name=self.read_text(), 
                english_name=self.read_text(),
                bone_index=self.read_bone_index_size(),
                collision_group=self.read_int(1),
                no_collision_group=self.read_int(2),
                shape_type=self.read_int(1),
                shape_size=self.read_Vector3D(),
                shape_position=self.read_Vector3D(),
                shape_rotation=self.read_Vector3D(),
                mass=self.read_float(),
                linear_damping=self.read_float(),
                angular_damping=self.read_float(),
                restitution=self.read_float(),
                friction=self.read_float(),
                mode=self.read_int(1)
            )

            pmx.rigidbodies[rigidbody.name] = rigidbody

        logger.debug("len(rigidbodies): %s", len(pmx.rigidbodies))

        # ジョイントデータリスト
        for _ in range(self.read_int(4)):      
            joint = PmxModel.Joint(
                name=self.read_text(),
                english_name=self.read_text(),
                joint_type=self.read_int(1),
                rigidbody_index_a=self.read_rigidbody_index_size(),
                rigidbody_index_b=self.read_rigidbody_index_size(),
                position=self.read_Vector3D(),
                rotation=self.read_Vector3D(),
                translation_limit_min=self.read_Vector3D(),
                translation_limit_max=self.read_Vector3D(),
                rotation_limit_min=self.read_Vector3D(),
                rotation_limit_max=self.read_Vector3D(),
                spring_constant_translation=self.read_Vector3D(),
                spring_constant_rotation=self.read_Vector3D()
            )

            pmx.joints[joint.name] = joint

        logger.debug("len(joints): %s", len(pmx.joints))

        # ハッシュを設定
        pmx.digest = self.hexdigest(filepath)
        logger.debug("pmx: %s, hash: %s", pmx.name, pmx.digest)

        # 腕がサイジング可能かチェック
        pmx.can_arm_sizing = pmx.check_arm_bone_can_sizing()
        logger.debug("pmx: %s, can_arm_sizing: %s", pmx.name, pmx.can_arm_sizing)

        return pmx
예제 #6
0
    def read_pmx_file(self, filename):
        # PMXファイルをバイナリ読み込み
        self.buffer = open(filename, "rb").read()
        
        # pmx宣言
        signature = self.unpack(4, "4s")        
        logger.debug("signature: %s (%s)", signature, self.offset)
        
        # pmxバージョン
        version = self.read_float()        
        logger.debug("version: %s (%s)", version, self.offset)
        
        if signature != b"PMX " or ( version != 2.0 and version != 2.1 ):
            # 整合性チェック
            raise ParseException("PMX2.0/2.1形式外のデータです。signature: {0}, version: {1} ".format(signature, version))
        
        # flag
        flag_bytes = self.read_int(1)
        logger.debug("flag_bytes: %s (%s)", flag_bytes, self.offset)
        
        # エンコード方式
        text_encoding = self.read_int(1)
        logger.debug("text_encoding: %s (%s)", text_encoding, self.offset)
        # エンコードに基づいて文字列解凍処理を定義
        self.read_text = self.define_read_text(text_encoding)
        
        # 追加UV数
        self.extended_uv = self.read_int(1)
        logger.debug("extended_uv: %s (%s)", self.extended_uv, self.offset)
        
        # 頂点Indexサイズ
        self.vertex_index_size = self.read_int(1)
        logger.debug("vertex_index_size: %s (%s)", self.vertex_index_size, self.offset)
        self.read_vertex_index_size = lambda : self.read_int(self.vertex_index_size)
        
        # テクスチャIndexサイズ
        self.texture_index_size = self.read_int(1)
        logger.debug("texture_index_size: %s (%s)", self.texture_index_size, self.offset)
        self.read_texture_index_size = lambda : self.read_int(self.texture_index_size)
        
        # 材質Indexサイズ
        self.material_index_size = self.read_int(1)
        logger.debug("material_index_size: %s (%s)", self.material_index_size, self.offset)
        self.read_material_index_size = lambda : self.read_int(self.material_index_size)
        
        # ボーンIndexサイズ
        self.bone_index_size = self.read_int(1)
        logger.debug("bone_index_size: %s (%s)", self.bone_index_size, self.offset)
        self.read_bone_index_size = lambda : self.read_int(self.bone_index_size)
        
        # モーフIndexサイズ
        self.morph_index_size = self.read_int(1)
        logger.debug("morph_index_size: %s (%s)", self.morph_index_size, self.offset)
        self.read_morph_index_size = lambda : self.read_int(self.morph_index_size)
        
        # 剛体Indexサイズ
        self.rigidbody_index_size = self.read_int(1)
        logger.debug("rigidbody_index_size: %s (%s)", self.rigidbody_index_size, self.offset)
        self.read_rigidbody_index_size = lambda : self.read_int(self.rigidbody_index_size)
        
        # Pmxモデル生成
        pmx = PmxModel()
        
        # モデル名(日本語)
        pmx.name = self.read_text()
        logger.debug("name: %s (%s)", pmx.name, self.offset)
        
        # モデル名(英語)
        pmx.english_name = self.read_text()
        logger.debug("english_name: %s (%s)", pmx.english_name, self.offset)
        
        # コメント(日本語)
        pmx.comment = self.read_text()
        logger.debug("comment: %s (%s)", pmx.comment, self.offset)
        
        # コメント(英語)
        pmx.english_comment = self.read_text()
        logger.debug("english_comment: %s (%s)", pmx.english_comment, self.offset)
        
        # 頂点データリスト
        for _ in range(self.read_int(4)):
            position = self.read_Vector3D()
            normal = self.read_Vector3D()
            uv = self.read_Vector2D()

            extended_uvs = []
            if self.extended_uv > 0:
                # 追加UVがある場合
                for _ in range(self.extended_uv):
                    extended_uvs.append(self.read_Vector4D())

            deform = self.read_deform()
            edge_factor = self.read_float()

            vindex = len(pmx.vertices)

            pmx.vertices.append(pmx.Vertex(vindex, position, normal, uv, extended_uvs, deform, edge_factor))
        logger.debug("len(vertices): %s", len(pmx.vertices))

        # 面データリスト
        for _ in range(self.read_int(4)):
            if self.vertex_index_size <= 2:
                # 頂点サイズが2以下の場合、符号なし
                pmx.indices.append(self.read_uint(self.vertex_index_size))
            else:
                pmx.indices.append(self.read_int(self.vertex_index_size))
        logger.debug("len(indices): %s", len(pmx.indices))
                
        # テクスチャデータリスト
        for _ in range(self.read_int(4)):
            pmx.textures.append(self.read_text())
        logger.debug("len(textures): %s", len(pmx.textures))

        # 材質データリスト
        for _ in range(self.read_int(4)):
            material = pmx.Material(
                name = self.read_text(),
                english_name = self.read_text(),
                diffuse_color = self.read_RGB(),
                alpha = self.read_float(),
                specular_color = self.read_RGB(),
                specular_factor = self.read_float(),
                ambient_color = self.read_RGB(),
                flag = self.read_int(1),
                edge_color = self.read_RGBA(),
                edge_size = self.read_float(),
                texture_index = self.read_texture_index_size(),
                sphere_texture_index = self.read_texture_index_size(),
                sphere_mode = self.read_int(1),
                toon_sharing_flag = self.read_int(1)
            )
            
            if material.toon_sharing_flag == 0:
                material.toon_texture_index = self.read_texture_index_size()
            elif material.toon_sharing_flag == 1:
                material.toon_texture_index = self.read_int(1)
            else:
                raise ParseException("unknown toon_sharing_flag {0}".format(material.toon_sharing_flag))
            material.comment = self.read_text()
            material.vertex_count = self.read_int(4)
            
            
            pmx.materials[material.name]  = material
        logger.debug("len(materials): %s", len(pmx.materials))

        # ボーンデータリスト
        for _ in range(self.read_int(4)):
            bone = pmx.Bone(
                name = self.read_text(),
                english_name = self.read_text(),
                position = self.read_Vector3D(),
                parent_index = self.read_bone_index_size(),
                layer = self.read_int(4),
                flag = self.read_int(2)
            )
            
            if not bone.getConnectionFlag():
                bone.tail_position = self.read_Vector3D()
            elif bone.getConnectionFlag():
                bone.tail_index = self.read_bone_index_size()
            else:
                raise ParseException("unknown bone conenction flag: {0}".format(bone.getConnectionFlag()))                

            if bone.getExternalRotationFlag() or bone.getExternalTranslationFlag():
                bone.effect_index = self.read_bone_index_size()
                bone.effect_factor = self.read_float()

            if bone.getFixedAxisFlag():
                bone.fixed_axis = self.read_Vector3D()

            if bone.getLocalCoordinateFlag():
                bone.local_x_vector = self.read_Vector3D()
                bone.local_z_vector = self.read_Vector3D()

            if bone.getExternalParentDeformFlag():
                bone.external_key = self.read_int(4)
                
            if bone.getIkFlag():
                bone.ik = pmx.Ik(
                        target_index = self.read_bone_index_size(),
                        loop = self.read_int(4),
                        limit_radian = self.read_float())
                
                # IKリンク取得
                for _ in range(self.read_int(4)):
                    
                    link = pmx.IkLink(
                            self.read_bone_index_size(),
                            self.read_int(1))
                    
                    if link.limit_angle == 0:
                        pass
                    elif link.limit_angle == 1:
                        link.limit_min = self.read_Vector3D()
                        link.limit_max = self.read_Vector3D()
                    else:
                        raise ParseException("invalid ik link limit_angle: {0}".format(link.limit_angle))
                    
                    bone.ik.link.append(link)

            # ボーンのINDEX
            bone.index = len(pmx.bones.keys())

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

        logger.debug("len(bones): %s", len(pmx.bones))
        
        # ボーンの長さを計算する
        self.calc_bone_length(pmx.bones, pmx.bone_indexes)

        # モーフデータリスト
        for _ in range(self.read_int(4)):      
            morph = PmxModel.Morph(
                name = self.read_text(),
                english_name = self.read_text(),
                panel=self.read_int(1),
                morph_type=self.read_int(1)
            )

            offset_size=self.read_int(4)

            if morph.morph_type==0:
                # group
                morph.offsets=[self.read_group_morph_data() for _ in range(offset_size)]
            elif morph.morph_type==1:
                # vertex
                morph.offsets=[self.read_vertex_position_morph_offset() for _ in range(offset_size)]
            elif morph.morph_type==2:
                # bone
                morph.offsets=[self.read_bone_morph_data() for _ in range(offset_size)]
            elif morph.morph_type==3:
                # uv
                morph.offsets=[self.read_uv_morph_data() for _ in range(offset_size)]
            elif morph.morph_type==4:
                # uv extended1
                morph.offsets=[self.read_uv_morph_data() for _ in range(offset_size)]
            elif morph.morph_type==5:
                # uv extended2
                morph.offsets=[self.read_uv_morph_data() for _ in range(offset_size)]
            elif morph.morph_type==6:
                # uv extended3
                morph.offsets=[self.read_uv_morph_data() for _ in range(offset_size)]
            elif morph.morph_type==7:
                # uv extended4
                morph.offsets=[self.read_uv_morph_data() for _ in range(offset_size)]
            elif morph.morph_type==8:
                # material
                morph.data=[self.read_material_morph_data() for _ in range(offset_size)]
            else:
                raise ParseException("unknown morph type: {0}".format(morph.morph_type))

            pmx.morphs[morph.name] = morph

        logger.debug("len(morphs): %s", len(pmx.morphs))

        # 表示枠データリスト
        for _ in range(self.read_int(4)):      
            display_slot = PmxModel.DisplaySlot(
                name = self.read_text(),
                english_name = self.read_text(),
                special_flag=self.read_int(1)
            )

            display_count=self.read_int(4)

            for _ in range(display_count):
                display_type=self.read_int(1)
                if display_type==0:
                    display_slot.references.append((display_type, self.read_bone_index_size()))
                elif display_type==1:
                    display_slot.references.append((display_type, self.read_morph_index_size()))
                else:
                    raise ParseException("unknown display_type: {0}".format(display_type))

            pmx.display_slots[display_slot.name] = display_slot

        logger.debug("len(display_slots): %s", len(pmx.display_slots))

        # 剛体データリスト
        for _ in range(self.read_int(4)):      
            rigidbody = PmxModel.RigidBody(
                name=self.read_text(), 
                english_name=self.read_text(),
                bone_index=self.read_bone_index_size(),
                collision_group=self.read_int(1),
                no_collision_group=self.read_int(2),
                shape_type=self.read_int(1),
                shape_size=self.read_Vector3D(),
                shape_position=self.read_Vector3D(),
                shape_rotation=self.read_Vector3D(),
                mass=self.read_float(),
                linear_damping=self.read_float(),
                angular_damping=self.read_float(),
                restitution=self.read_float(),
                friction=self.read_float(),
                mode=self.read_int(1)
            )

            pmx.rigidbodies[rigidbody.name] = rigidbody

        logger.debug("len(rigidbodies): %s", len(pmx.rigidbodies))

        # ジョイントデータリスト
        for _ in range(self.read_int(4)):      
            joint = PmxModel.Joint(
                name=self.read_text(),
                english_name=self.read_text(),
                joint_type=self.read_int(1),
                rigidbody_index_a=self.read_rigidbody_index_size(),
                rigidbody_index_b=self.read_rigidbody_index_size(),
                position=self.read_Vector3D(),
                rotation=self.read_Vector3D(),
                translation_limit_min=self.read_Vector3D(),
                translation_limit_max=self.read_Vector3D(),
                rotation_limit_min=self.read_Vector3D(),
                rotation_limit_max=self.read_Vector3D(),
                spring_constant_translation=self.read_Vector3D(),
                spring_constant_rotation=self.read_Vector3D()
            )

            pmx.joints[joint.name] = joint

        logger.debug("len(joints): %s", len(pmx.joints))

        return pmx