From cf6ec3e04ee67bbe635510486475961ed32e46f2 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Tue, 4 Oct 2011 02:20:50 +0900 Subject: [PATCH] implement pmx.writer --- pymeshio/common.py | 12 +- pymeshio/pmd/writer.py | 30 ++--- pymeshio/pmx/__init__.py | 195 +++++++++++++++++++++------- pymeshio/pmx/reader.py | 8 +- pymeshio/pmx/writer.py | 326 +++++++++++++++++++++++++++++++++++++++++++++++ test/pmx_test.py | 13 ++ 6 files changed, 520 insertions(+), 64 deletions(-) create mode 100644 pymeshio/pmx/writer.py diff --git a/pymeshio/common.py b/pymeshio/common.py index 45a7ff0..7177506 100644 --- a/pymeshio/common.py +++ b/pymeshio/common.py @@ -243,6 +243,9 @@ class RGBA(object): self.b=b self.a=a + def __eq__(self, rhs): + return self.r==rhs.r and self.g==rhs.g and self.b==rhs.b and self.a==rhs.a + def __getitem__(self, key): if key==0: return self.r @@ -331,11 +334,15 @@ class BinaryReader(object): ) +class WriteException(Exception): + pass + + class BinaryWriter(object): def __init__(self, ios): self.ios=ios - def write_text(self, v, size=None): + def write_bytes(self, v, size=None): if size: self.ios.write(struct.pack("={0}s".format(size), v)) else: @@ -363,4 +370,7 @@ class BinaryWriter(object): def write_rgb(self, v): self.ios.write(struct.pack("=3f", v.r, v.g, v.b)) + def write_rgba(self, v): + self.ios.write(struct.pack("=4f", v.r, v.g, v.b, v.a)) + diff --git a/pymeshio/pmd/writer.py b/pymeshio/pmd/writer.py index 187f59d..0e7ec0d 100644 --- a/pymeshio/pmd/writer.py +++ b/pymeshio/pmd/writer.py @@ -32,14 +32,14 @@ class Writer(common.BinaryWriter): self.write_uint(m.toon_index, 1) self.write_uint(m.edge_flag, 1) self.write_uint(m.vertex_count, 4) - self.write_text(m.texture_file, 20) + self.write_bytes(m.texture_file, 20) def write_bones(self, bones): self.write_uint(len(bones), 2) sBone=struct.Struct("=20sHHBH3f") assert(sBone.size==39) for b in bones: - self.write_text(b.name, 20) + self.write_bytes(b.name, 20) self.write_uint(b.parent_index, 2) self.write_uint(b.tail_index, 2) self.write_uint(b.type, 1) @@ -59,7 +59,7 @@ class Writer(common.BinaryWriter): def write_morphs(self, morphs): self.write_uint(len(morphs), 2) for morph in morphs: - self.write_text(morph.name, 20) + self.write_bytes(morph.name, 20) self.write_uint(len(morph.indices), 4) self.write_uint(morph.type, 1) for i, v in zip(morph.indices, morph.pos_list): @@ -73,7 +73,7 @@ class Writer(common.BinaryWriter): def write_bone_group_list(self, bone_group_list): self.write_uint(len(bone_group_list), 1) for g in bone_group_list: - self.write_text(g.name, 50) + self.write_bytes(g.name, 50) def write_bone_display_list(self, bone_display_list): self.write_uint(len(bone_display_list), 4) @@ -84,7 +84,7 @@ class Writer(common.BinaryWriter): def write_rigidbodies(self, rigidbodies): self.write_uint(len(rigidbodies), 4) for r in rigidbodies: - self.write_text(r.name, 20) + self.write_bytes(r.name, 20) self.write_uint(r.bone_index, 2) self.write_uint(r.collision_group, 1) self.write_uint(r.no_collision_group, 2) @@ -102,7 +102,7 @@ class Writer(common.BinaryWriter): def write_joints(self, joints): self.write_uint(len(joints), 4) for j in joints: - self.write_text(j.name, 20) + self.write_bytes(j.name, 20) self.write_uint(j.rigidbody_index_a, 4) self.write_uint(j.rigidbody_index_b, 4) self.write_vector3(j.position) @@ -119,10 +119,10 @@ def write(ios, model): assert(isinstance(ios, io.IOBase)) assert(isinstance(model, pmd.Model)) writer=Writer(ios) - writer.write_text(b"Pmd") + writer.write_bytes(b"Pmd") writer.write_float(model.version) - writer.write_text(model.name, 20) - writer.write_text(model.comment, 256) + writer.write_bytes(model.name, 20) + writer.write_bytes(model.comment, 256) writer.write_veritices(model.vertices) writer.write_indices(model.indices) writer.write_materials(model.materials) @@ -134,18 +134,18 @@ def write(ios, model): writer.write_bone_display_list(model.bone_display_list) # extend data writer.write_uint(1, 1) - writer.write_text(model.english_name, 20) - writer.write_text(model.english_comment, 256) + writer.write_bytes(model.english_name, 20) + writer.write_bytes(model.english_comment, 256) for bone in model.bones: - writer.write_text(bone.english_name, 20) + writer.write_bytes(bone.english_name, 20) for skin in model.morphs: if skin.name==b'base': continue - writer.write_text(skin.english_name, 20) + writer.write_bytes(skin.english_name, 20) for g in model.bone_group_list: - writer.write_text(g.english_name, 50) + writer.write_bytes(g.english_name, 50) for toon_texture in model.toon_textures: - writer.write_text(toon_texture, 100) + writer.write_bytes(toon_texture, 100) writer.write_rigidbodies(model.rigidbodies) writer.write_joints(model.joints) return True diff --git a/pymeshio/pmx/__init__.py b/pymeshio/pmx/__init__.py index d5665dc..42b15f6 100644 --- a/pymeshio/pmx/__init__.py +++ b/pymeshio/pmx/__init__.py @@ -81,13 +81,23 @@ class Bone(object): layer, flag ): - self.name=name, + self.name=name self.english_name=english_name self.position=position self.parent_index=parent_index self.layer=layer self.flag=flag + def __eq__(self, rhs): + return ( + self.name==rhs.name + and self.english_name==rhs.english_name + and self.position==rhs.position + and self.parent_index==rhs.parent_index + and self.layer==rhs.layer + and self.flag==rhs.flag + ) + def getConnectionFlag(self): return self.flag & 0x0001 @@ -119,7 +129,7 @@ class Material(object): 'name', 'english_name', 'diffuse_color', - 'diffuse_alpha', + 'alpha', 'specular_color', 'specular_factor', 'ambient_color', @@ -127,8 +137,8 @@ class Material(object): 'edge_color', 'edge_size', 'texture_index', - 'sphia_texture_index', - 'sphia_mode', + 'sphere_texture_index', + 'sphere_mode', 'toon_sharing_flag', 'toon_texture_index', 'comment', @@ -138,7 +148,7 @@ class Material(object): name, english_name, diffuse_color, - diffuse_alpha, + alpha, specular_color, specular_factor, ambient_color, @@ -146,14 +156,14 @@ class Material(object): edge_color, edge_size, texture_index, - sphia_texture_index, - sphia_mode, + sphere_texture_index, + sphere_mode, toon_sharing_flag ): self.name=name self.english_name=english_name self.diffuse_color=diffuse_color - self.diffuse_alpha=diffuse_alpha + self.alpha=alpha self.specular_color=specular_color self.specular_factor=specular_factor self.ambient_color=ambient_color @@ -161,14 +171,35 @@ class Material(object): self.edge_color=edge_color self.edge_size=edge_size self.texture_index=texture_index - self.sphia_texture_index=sphia_texture_index - self.sphia_mode=sphia_mode + self.sphere_texture_index=sphere_texture_index + self.sphere_mode=sphere_mode self.toon_sharing_flag=toon_sharing_flag # self.toon_texture_index=None - self.comment='' + self.comment=name.__class__() # unicode self.vertex_count=0 + def __eq__(self, rhs): + return ( + self.name==rhs.name + and self.english_name==rhs.english_name + and self.diffuse_color==rhs.diffuse_color + and self.alpha==rhs.alpha + and self.specular_color==rhs.specular_color + and self.specular_factor==rhs.specular_factor + and self.ambient_color==rhs.ambient_color + and self.flag==rhs.flag + and self.edge_color==rhs.edge_color + and self.edge_size==rhs.edge_size + and self.texture_index==rhs.texture_index + and self.sphere_texture_index==rhs.sphere_texture_index + and self.sphere_mode==rhs.sphere_mode + and self.toon_sharing_flag==rhs.toon_sharing_flag + and self.toon_texture_index==rhs.toon_texture_index + and self.comment==rhs.comment + and self.vertex_count==rhs.vertex_count + ) + def __str__(self): return ("".format( name=self.english_name @@ -188,6 +219,9 @@ class Bdef1(object): def __init__(self, index0): self.index0=index0 + def __eq__(self, rhs): + return self.index0==rhs.index0 + class Bdef2(object): """bone deform. use two weights @@ -203,6 +237,13 @@ class Bdef2(object): self.index1=index1 self.weight0=weight0 + def __eq__(self, rhs): + return ( + self.index0==rhs.index0 + and self.index1==rhs.index1 + and self.weight0==rhs.weight0 + ) + class Vertex(object): """pmx vertex @@ -222,6 +263,15 @@ class Vertex(object): self.deform=deform self.edge_factor=edge_factor + def __eq__(self, rhs): + return ( + self.position==rhs.position + and self.normal==rhs.normal + and self.uv==rhs.uv + and self.deform==rhs.deform + and self.edge_factor==rhs.edge_factor + ) + class Morph(object): """pmx morph @@ -247,6 +297,15 @@ class Morph(object): self.morph_type=morph_type self.offsets=[] + def __eq__(self, rhs): + return ( + self.name==rhs.name + and self.english_name==rhs.english_name + and self.panel==rhs.panel + and self.morph_type==rhs.morph_type + and self.offsets==rhs.offsets + ) + class VerexMorphOffset(object): """pmx vertex morph offset @@ -263,6 +322,12 @@ class VerexMorphOffset(object): self.vertex_index=vertex_index self.position_offset=position_offset + def __eq__(self, rhs): + return ( + self.vertex_index==rhs.vertex_index + and self.position_offset==rhs.position_offset + ) + class DisplaySlot(object): """pmx display slot @@ -285,30 +350,13 @@ class DisplaySlot(object): self.special_flag=special_flag self.refrences=[] - -class Shape(object): - pass - - -class SphereShape(Shape): - __slots__=['radius'] - def __init__(self, radius): - self.radius=radius - - -class CapsuleShape(Shape): - __slots__=['short_radius', 'long_radius'] - def __init__(self, short_radius, long_radius): - self.short_radius=short_radius - self.long_radius=long_radius - - -class BoxShape(Shape): - __slots__=['x', 'y', 'z'] - def __init__(self, x, y, z): - self.x=x - self.y=y - self.z=z + def __eq__(self, rhs): + return ( + self.name==rhs.name + and self.english_name==rhs.english_name + and self.special_flag==rhs.special_flag + and self.refrences==rhs.refrences + ) class RigidBodyParam(object): @@ -336,6 +384,15 @@ class RigidBodyParam(object): self.restitution=restitution self.friction=friction + def __eq__(self, rhs): + return ( + self.mass==rhs.mass + and self.linear_damping==rhs.linear_damping + and self.angular_damping==rhs.angular_damping + and self.restitution==rhs.restitution + and self.friction==rhs.friction + ) + class RigidBody(object): """pmx rigidbody @@ -356,7 +413,10 @@ class RigidBody(object): 'bone_index', 'collision_group', 'no_collision_group', - 'shape', + 'shape_type', + 'shape_size', + 'shape_position', + 'shape_rotation', 'param', 'mode', ] @@ -382,20 +442,28 @@ class RigidBody(object): self.bone_index=bone_index self.collision_group=collision_group self.no_collision_group=no_collision_group - if shape_type==0: - self.shape=SphereShape(shape_size.x) - elif shape_type==1: - self.shape=BoxShape(shape_size.x, shape_size.y, shape_size.z) - elif shape_type==2: - self.shape=CapsuleShape(shape_size.x, shape_size.y) - else: - raise pymeshio.common.ParseException( - "unknown shape_type: {0}".format(shape_type)) + self.shape_type=shape_type + self.shape_size=shape_size + self.shape_position=shape_position + self.shape_rotation=shape_rotation self.param=RigidBodyParam(mass, linear_damping, angular_damping, restitution, friction) self.mode=mode + def __eq__(self, rhs): + return ( + self.name==rhs.name + and self.english_name==rhs.english_name + and self.bone_index==rhs.bone_index + and self.collision_group==rhs.collision_group + and self.no_collision_group==rhs.no_collision_group + and self.shape_type==rhs.shape_type + and self.shape_size==rhs.shape_size + and self.param==rhs.param + and self.mode==rhs.mode + ) + class Joint(object): """pmx joint @@ -457,6 +525,23 @@ class Joint(object): self.spring_constant_translation=spring_constant_translation self.spring_constant_rotation=spring_constant_rotation + def __eq__(self, rhs): + return ( + self.name==rhs.name + and self.english_name==rhs.english_name + and self.joint_type==rhs.joint_type + and self.rigidbody_index_a==rhs.rigidbody_index_a + and self.rigidbody_index_b==rhs.rigidbody_index_b + and self.position==rhs.position + and self.rotation==rhs.rotation + and self.translation_limit_min==rhs.translation_limit_min + and self.translation_limit_max==rhs.translation_limit_max + and self.rotation_limit_min==rhs.rotation_limit_min + and self.rotation_limit_max==rhs.rotation_limit_max + and self.spring_constant_translation==rhs.spring_constant_translation + and self.spring_constant_rotation==rhs.spring_constant_rotation + ) + class Model(object): """pmx data representation @@ -503,6 +588,8 @@ class Model(object): self.textures=[] self.materials=[] self.bones=[] + self.morphs=[] + self.display_slots=[] self.rigidbodies=[] self.joints=[] @@ -513,3 +600,21 @@ class Model(object): vertices=len(self.vertices) )) + def __eq__(self, rhs): + return ( + self.version==rhs.version + and self.name==rhs.name + and self.english_name==rhs.english_name + and self.comment==rhs.comment + and self.english_comment==rhs.english_comment + and self.vertices==rhs.vertices + and self.indices==rhs.indices + and self.textures==rhs.textures + and self.materials==rhs.materials + and self.bones==rhs.bones + and self.morphs==rhs.morphs + and self.display_slots==rhs.display_slots + and self.rigidbodies==rhs.rigidbodies + and self.joints==rhs.joints + ) + diff --git a/pymeshio/pmx/reader.py b/pymeshio/pmx/reader.py index 40358bb..a95ab21 100644 --- a/pymeshio/pmx/reader.py +++ b/pymeshio/pmx/reader.py @@ -78,7 +78,7 @@ class Reader(pymeshio.common.BinaryReader): name=self.read_text(), english_name=self.read_text(), diffuse_color=self.read_rgb(), - diffuse_alpha=self.read_float(), + alpha=self.read_float(), specular_color=self.read_rgb(), specular_factor=self.read_float(), ambient_color=self.read_rgb(), @@ -86,8 +86,8 @@ class Reader(pymeshio.common.BinaryReader): edge_color=self.read_rgba(), edge_size=self.read_float(), texture_index=self.read_texture_index(), - sphia_texture_index=self.read_texture_index(), - sphia_mode=self.read_uint(1), + sphere_texture_index=self.read_texture_index(), + sphere_mode=self.read_uint(1), toon_sharing_flag=self.read_uint(1), ) if material.toon_sharing_flag==0: @@ -147,6 +147,7 @@ class Reader(pymeshio.common.BinaryReader): link_size=self.read_uint(4) ik.link=[self.read_ik_link() for _ in range(link_size)] + return ik def read_ik_link(self): link=pymeshio.pmx.IkLink( @@ -230,6 +231,7 @@ class Reader(pymeshio.common.BinaryReader): else: raise pymeshio.common.ParseException( "unknown display_type: {0}".format(display_type)) + return display_slot def read_rigidbody(self): return pymeshio.pmx.RigidBody( diff --git a/pymeshio/pmx/writer.py b/pymeshio/pmx/writer.py new file mode 100644 index 0000000..073a665 --- /dev/null +++ b/pymeshio/pmx/writer.py @@ -0,0 +1,326 @@ +# coding: utf-8 +import io +import struct +from .. import common +from .. import pmx + +class Writer(common.BinaryWriter): + """pmx writer + """ + def __init__(self, ios, + text_encoding, extended_uv, + vertex_index_size, texture_index_size, material_index_size, + bone_index_size, morph_index_size, rigidbody_index_size): + super(Writer, self).__init__(ios) + if text_encoding==0: + def write_text(unicode): + utf16=unicode.encode('utf16') + self.write_uint(len(utf16), 4) + self.write_bytes(utf16) + self.write_text=write_text + elif text_encoding==1: + def write_text(unicode): + utf8=unicode.encode('utf8') + self.write_uint(len(utf8), 4) + self.write_bytes(utf8) + self.write_text=write_text + else: + raise WriteError( + "invalid text_encoding: {0}".format(text_encoding)) + + self.write_vertex_index=lambda index: self.write_uint(index, vertex_index_size) + self.write_texture_index=lambda index: self.write_uint(index, texture_index_size) + self.write_material_index=lambda index: self.write_uint(index, material_index_size) + self.write_bone_index=lambda index: self.write_uint(index, bone_index_size) + self.write_morph_index=lambda index: self.write_uint(index, morph_index_size) + self.write_rigidbody_index=lambda index: self.write_uint(index, rigidbody_index_size) + + def write_vertices(self, vertices): + self.write_uint(len(vertices), 4) + for v in vertices: + self.write_vector3(v.position) + self.write_vector3(v.normal) + self.write_vector2(v.uv) + self.write_deform(v.deform) + self.write_float(v.edge_factor) + + def write_deform(self, deform): + if isinstance(deform, pmx.Bdef1): + self.write_uint(0, 1) + self.write_bone_index(deform.index0) + elif isinstance(deform, pmx.Bdef2): + self.write_uint(1, 1) + self.write_bone_index(deform.index0) + self.write_bone_index(deform.index1) + self.write_float(deform.weight0) + elif isinstance(deform, pmx.Bdef4): + # todo + raise pymeshio.common.WriteException( + "not implemented Bdef4") + else: + raise pymeshio.common.WriteException( + "unknown deform type: {0}".format(deform.type)) + + def write_indices(self, indices): + self.write_uint(len(indices), 4) + for i in indices: + self.write_vertex_index(i) + + def write_textures(self, textures): + self.write_uint(len(textures), 4) + for t in textures: + self.write_text(t) + + def write_materials(self, materials): + self.write_uint(len(materials), 4) + for m in materials: + self.write_text(m.name) + self.write_text(m.english_name) + self.write_rgb(m.diffuse_color) + self.write_float(m.alpha) + self.write_rgb(m.specular_color) + self.write_float(m.specular_factor) + self.write_rgb(m.ambient_color) + self.write_uint(m.flag, 1) + self.write_rgba(m.edge_color) + self.write_float(m.edge_size) + self.write_texture_index(m.texture_index) + self.write_texture_index(m.sphere_texture_index) + self.write_uint(m.sphere_mode, 1) + self.write_uint(m.toon_sharing_flag, 1) + if m.toon_sharing_flag==0: + self.write_texture_index(m.toon_texture_index) + elif m.toon_sharing_flag==1: + self.write_uint(m.toon_texture_index, 1) + else: + raise common.WriteException( + "unknown toon_sharing_flag {0}".format(m.toon_sharing_flag)) + self.write_text(m.comment) + self.write_uint(m.vertex_count, 4) + + def write_bones(self, bones): + self.write_uint(len(bones), 4) + for bone in bones: + self.write_text(bone.name) + self.write_text(bone.english_name) + self.write_vector3(bone.position) + self.write_bone_index(bone.parent_index) + self.write_uint(bone.layer, 4) + self.write_uint(bone.flag, 2) + if bone.getConnectionFlag()==0: + self.write_vector3(bone.tail_positoin) + elif bone.getConnectionFlag()==1: + self.write_bone_index(bone.tail_index) + else: + raise pymeshio.common.WriteException( + "unknown bone conenction flag: {0}".format( + bone.getConnectionFlag())) + + if bone.getRotationFlag()==1 or bone.getTranslationFlag()==1: + self.write_bone_index(bone.effect_index) + self.write_float(bone.effect_factor) + + if bone.getFixedAxisFlag()==1: + self.write_vector3(bone.fixed_axis) + + if bone.getLocalCoordinateFlag()==1: + self.write_vector3(bone.local_x_vector) + self.write_vector3(bone.local_z_vector) + + if bone.getExternalParentDeformFlag()==1: + self.write_uint(bone.external_key, 4) + + if bone.getIkFlag()==1: + self.write_ik(bone.ik) + + def write_ik(self, ik): + self.write_bone_index(ik.target_index) + self.write_uint(ik.loop, 4) + self.write_float(ik.limit_radian) + self.write_uint(len(ik.link), 4) + for l in ik.link: + self.write_ik_link(l) + + def write_ik_link(self, link): + self.write_bone_index(link.bone_index) + self.write_uint(link.limit_angle, 1) + if link.limit_angle==0: + pass + elif link.limit_angle==1: + self.write_vector3(link.limit_min) + self.write_vector3(link.limit_max) + else: + raise pymeshio.common.WriteException( + "invalid ik link limit_angle: {0}".format( + link.limit_angle)) + + def write_morph(self, morphs): + self.write_uint(len(morphs), 4) + for m in morphs: + self.write_text(m.name) + self.write_text(m.english_name) + self.write_uint(m.panel, 1) + self.write_uint(m.morph_type, 1) + if m.morph_type==0: + # todo + raise pymeshio.common.WriteException( + "not implemented GroupMorph") + elif m.morph_type==1: + self.write_uint(len(m.offsets), 4) + for o in m.offsets: + self.write_vertex_index(o.vertex_index) + self.write_vector3(o.position_offset) + elif m.morph_type==2: + # todo + raise pymeshio.common.WriteException( + "not implemented BoneMorph") + elif m.morph_type==3: + # todo + raise pymeshio.common.WriteException( + "not implemented UvMorph") + elif m.morph_type==4: + # todo + raise pymeshio.common.WriteException( + "not implemented extended UvMorph1") + elif m.morph_type==5: + # todo + raise pymeshio.common.WriteException( + "not implemented extended UvMorph2") + elif m.morph_type==6: + # todo + raise pymeshio.common.WriteException( + "not implemented extended UvMorph3") + elif m.morph_type==7: + # todo + raise pymeshio.common.WriteException( + "not implemented extended UvMorph4") + elif m.morph_type==8: + # todo + raise pymeshio.common.WriteException( + "not implemented extended MaterialMorph") + else: + raise pymeshio.common.WriteException( + "unknown morph type: {0}".format(m.morph_type)) + + def write_display_slots(self, display_slots): + self.write_uint(len(display_slots), 4) + for s in display_slots: + self.write_text(s.name) + self.write_text(s.english_name) + self.write_uint(s.special_flag, 1) + self.write_uint(len(s.refrences), 4) + for r in s.refrences: + self.write_uint(r[0], 1) + if r[0]==0: + self.write_bone_index(r[1]) + elif r[0]==1: + self.write_morph_index(r[1]) + else: + raise pymeshio.common.WriteException( + "unknown display_type: {0}".format(r[0])) + + def write_rigidbodies(self, rigidbodies): + self.write_uint(len(rigidbodies), 4) + for rb in rigidbodies: + self.write_text(rb.name) + self.write_text(rb.english_name) + self.write_bone_index(rb.bone_index) + self.write_uint(rb.collision_group, 1) + self.write_uint(rb.no_collision_group, 2) + self.write_uint(rb.shape_type, 1) + self.write_vector3(rb.shape_size) + self.write_vector3(rb.shape_position) + self.write_vector3(rb.shape_rotation) + self.write_float(rb.param.mass) + self.write_float(rb.param.linear_damping) + self.write_float(rb.param.angular_damping) + self.write_float(rb.param.restitution) + self.write_float(rb.param.friction) + self.write_uint(rb.mode, 1) + + def write_joints(self, joints): + self.write_uint(len(joints), 4) + for j in joints: + self.write_text(j.name) + self.write_text(j.english_name) + self.write_uint(j.joint_type, 1) + self.write_rigidbody_index(j.rigidbody_index_a) + self.write_rigidbody_index(j.rigidbody_index_b) + self.write_vector3(j.position) + self.write_vector3(j.rotation) + self.write_vector3(j.translation_limit_min) + self.write_vector3(j.translation_limit_max) + self.write_vector3(j.rotation_limit_min) + self.write_vector3(j.rotation_limit_max) + self.write_vector3(j.spring_constant_translation) + self.write_vector3(j.spring_constant_rotation) + + +def write(ios, model, text_encoding=1): + """pmx‘‚«ž‚Ý + """ + assert(isinstance(ios, io.IOBase)) + assert(isinstance(model, pmx.Model)) + writer=common.BinaryWriter(ios) + # header + writer.write_bytes(b"PMX ") + writer.write_float(model.version) + + # flags + writer.write_uint(8, 1) + # textencoding + writer.write_uint(text_encoding, 1) + # extend uv + writer.write_uint(0, 1) + def get_array_size(size): + if size<128: + return 1 + elif size<32768: + return 2 + elif size<2147483647: + return 4 + else: + raise common.WriteError( + "invalid array_size: {0}".format(size)) + # vertex_index_size + vertex_index_size=get_array_size(len(model.vertices)) + writer.write_uint(vertex_index_size, 1) + # texture_index_size + texture_index_size=get_array_size(len(model.textures)) + writer.write_uint(texture_index_size, 1) + # material_index_size + material_index_size=get_array_size(len(model.materials)) + writer.write_uint(material_index_size, 1) + # bone_index_size + bone_index_size=get_array_size(len(model.bones)) + writer.write_uint(bone_index_size, 1) + # morph_index_size + morph_index_size=get_array_size(len(model.morphs)) + writer.write_uint(morph_index_size, 1) + # rigidbody_index_size + rigidbody_index_size=get_array_size(len(model.rigidbodies)) + writer.write_uint(rigidbody_index_size, 1) + + writer=Writer(writer.ios, + text_encoding, 0, + vertex_index_size, texture_index_size, material_index_size, + bone_index_size, morph_index_size, rigidbody_index_size) + + # model info + writer.write_text(model.name) + writer.write_text(model.english_name) + writer.write_text(model.comment) + writer.write_text(model.english_comment) + + # model data + writer.write_vertices(model.vertices) + writer.write_indices(model.indices) + writer.write_textures(model.textures) + writer.write_materials(model.materials) + writer.write_bones(model.bones) + writer.write_morph(model.morphs) + writer.write_display_slots(model.display_slots) + writer.write_rigidbodies(model.rigidbodies) + writer.write_joints(model.joints) + return True + diff --git a/test/pmx_test.py b/test/pmx_test.py index 1e89b0d..e9185ee 100644 --- a/test/pmx_test.py +++ b/test/pmx_test.py @@ -1,7 +1,9 @@ # coding: utf-8 import unittest +import io import pymeshio.pmd import pymeshio.pmx.reader +import pymeshio.pmx.writer PMX_FILE=pymeshio.unicode('resources/初音ミクVer2.pmx') @@ -44,3 +46,14 @@ class TestPmx(unittest.TestCase): self.assertEqual(45, len(model.rigidbodies)) self.assertEqual(27, len(model.joints)) + def test_write(self): + # read source file + buf=pymeshio.common.readall(PMX_FILE) + # read and write to out + model=pymeshio.pmx.reader.read(io.BytesIO(buf)) + out=io.BytesIO() + pymeshio.pmx.writer.write(out, model) + # read out buffer again + model2=pymeshio.pmx.reader.read(io.BytesIO(out.getvalue())) + self.assertEqual(model, model2) + -- 2.11.0