pmdとmqoの入出力ライブラリと、それを使ったBlender2.5向けのaddon。
Revision | c857394d134621b15569d4dbef60cfd62541bcac (tree) |
---|---|
Time | 2011-10-15 22:09:29 |
Author | ousttrue <ousttrue@gmai...> |
Commiter | ousttrue |
implementing export_pmx...
@@ -43,6 +43,21 @@ def create_pmx(ex): | ||
43 | 43 | ) |
44 | 44 | for pos, attribute, b0, b1, weight in ex.oneSkinMesh.vertexArray.zip()] |
45 | 45 | |
46 | + ''' | |
47 | + # IK | |
48 | + for ik in self.skeleton.ik_list: | |
49 | + solver=pmd.IK() | |
50 | + solver.index=self.skeleton.getIndex(ik.target) | |
51 | + solver.target=self.skeleton.getIndex(ik.effector) | |
52 | + solver.length=ik.length | |
53 | + b=self.skeleton.bones[ik.effector.parent_index] | |
54 | + for i in range(solver.length): | |
55 | + solver.children.append(self.skeleton.getIndex(b)) | |
56 | + b=self.skeleton.bones[b.parent_index] | |
57 | + solver.iterations=ik.iterations | |
58 | + solver.weight=ik.weight | |
59 | + model.ik_list.append(solver) | |
60 | + ''' | |
46 | 61 | def create_bone(b): |
47 | 62 | return pmx.Bone( |
48 | 63 | name=b.name, |
@@ -69,171 +84,105 @@ def create_pmx(ex): | ||
69 | 84 | model.bones=[create_bone(b) |
70 | 85 | for b in ex.skeleton.bones] |
71 | 86 | |
72 | - return model | |
73 | - | |
74 | - # IK | |
75 | - for ik in self.skeleton.ik_list: | |
76 | - solver=pmd.IK() | |
77 | - solver.index=self.skeleton.getIndex(ik.target) | |
78 | - solver.target=self.skeleton.getIndex(ik.effector) | |
79 | - solver.length=ik.length | |
80 | - b=self.skeleton.bones[ik.effector.parent_index] | |
81 | - for i in range(solver.length): | |
82 | - solver.children.append(self.skeleton.getIndex(b)) | |
83 | - b=self.skeleton.bones[b.parent_index] | |
84 | - solver.iterations=ik.iterations | |
85 | - solver.weight=ik.weight | |
86 | - model.ik_list.append(solver) | |
87 | + textures=set() | |
88 | + def get_texture_name(texture): | |
89 | + pos=texture.replace("\\", "/").rfind("/") | |
90 | + if pos==-1: | |
91 | + return texture | |
92 | + else: | |
93 | + return texture[pos+1:] | |
94 | + for m in ex.oneSkinMesh.vertexArray.indexArrays.keys(): | |
95 | + for path in bl.material.eachEnalbeTexturePath(bl.material.get(m)): | |
96 | + textures.add(get_texture_name(path)) | |
97 | + model.textures=list(textures) | |
87 | 98 | |
88 | 99 | # 面とマテリアル |
89 | - vertexCount=self.oneSkinMesh.getVertexCount() | |
90 | - for material_name, indices in self.oneSkinMesh.vertexArray.each(): | |
100 | + vertexCount=ex.oneSkinMesh.getVertexCount() | |
101 | + for material_name, indices in ex.oneSkinMesh.vertexArray.each(): | |
91 | 102 | #print('material:', material_name) |
92 | 103 | try: |
93 | 104 | m=bl.material.get(material_name) |
94 | 105 | except KeyError as e: |
95 | 106 | m=DefaultMatrial() |
96 | - def get_texture_name(texture): | |
97 | - pos=texture.replace("\\", "/").rfind("/") | |
98 | - if pos==-1: | |
99 | - return texture | |
100 | - else: | |
101 | - return texture[pos+1:] | |
102 | - textures=[get_texture_name(path) | |
103 | - for path in bl.material.eachEnalbeTexturePath(m)] | |
104 | - print(textures) | |
105 | 107 | # マテリアル |
106 | - model.materials.append(pmd.Material( | |
107 | - # diffuse_color | |
108 | - common.RGB(m.diffuse_color[0], m.diffuse_color[1], m.diffuse_color[2]), | |
109 | - m.alpha, | |
110 | - # specular_factor | |
111 | - 0 if m.specular_toon_size<1e-5 else m.specular_hardness*10, | |
112 | - # specular_color | |
113 | - common.RGB(m.specular_color[0], m.specular_color[1], m.specular_color[2]), | |
114 | - # ambient_color | |
115 | - common.RGB(m.mirror_color[0], m.mirror_color[1], m.mirror_color[2]), | |
116 | - # flag | |
117 | - 1 if m.subsurface_scattering.use else 0, | |
118 | - # toon | |
119 | - 0, | |
120 | - # vertex_count | |
121 | - len(indices), | |
122 | - # texture | |
123 | - ('*'.join(textures) if len(textures)>0 else "").encode('cp932') | |
108 | + model.materials.append(pmx.Material( | |
109 | + name=m.name, | |
110 | + english_name='', | |
111 | + diffuse_color=common.RGB(m.diffuse_color[0], m.diffuse_color[1], m.diffuse_color[2]), | |
112 | + alpha=m.alpha, | |
113 | + specular_factor=0 if m.specular_toon_size<1e-5 else m.specular_hardness*10, | |
114 | + specular_color=common.RGB(m.specular_color[0], m.specular_color[1], m.specular_color[2]), | |
115 | + ambient_color=common.RGB(m.mirror_color[0], m.mirror_color[1], m.mirror_color[2]), | |
116 | + flag=1 if m.subsurface_scattering.use else 0, | |
117 | + edge_color=common.RGBA(0, 0, 0, 1), | |
118 | + edge_size=1.0, | |
119 | + texture_index=0, | |
120 | + sphere_texture_index=0, | |
121 | + sphere_mode=0, | |
122 | + toon_sharing_flag=0, | |
123 | + toon_texture_index=0, | |
124 | + comment='', | |
125 | + vertex_count=len(indices) | |
124 | 126 | )) |
125 | 127 | # 面 |
126 | 128 | for i in indices: |
127 | 129 | assert(i<vertexCount) |
128 | 130 | for i in range(0, len(indices), 3): |
129 | 131 | # reverse triangle |
130 | - model.indices.append(indices[i]) | |
131 | - model.indices.append(indices[i+1]) | |
132 | 132 | model.indices.append(indices[i+2]) |
133 | + model.indices.append(indices[i+1]) | |
134 | + model.indices.append(indices[i]) | |
133 | 135 | |
134 | 136 | # 表情 |
135 | - for i, m in enumerate(self.oneSkinMesh.morphList): | |
136 | - v=englishmap.getUnicodeSkinName(m.name) | |
137 | - if not v: | |
138 | - v=[m.name, m.name, 0] | |
139 | - assert(v) | |
140 | - # morph | |
141 | - morph=pmd.Morph(v[1].encode("cp932")) | |
142 | - morph.english_name=m.name.encode("cp932") | |
143 | - m.type=v[2] | |
144 | - morph.type=v[2] | |
145 | - for index, offset in m.offsets: | |
146 | - # convert right-handed z-up to left-handed y-up | |
147 | - morph.append(index, offset[0], offset[2], offset[1]) | |
148 | - morph.vertex_count=len(m.offsets) | |
137 | + for i, m in enumerate(ex.oneSkinMesh.morphList): | |
138 | + morph=pmx.Morph( | |
139 | + name=m.name, | |
140 | + english_name='', | |
141 | + panel=0, | |
142 | + morph_type=1, | |
143 | + ) | |
144 | + morph.offsets=[pmx.VertexMorphOffset( | |
145 | + index, | |
146 | + common.Vector3(offset[0], offset[2], offset[1]) | |
147 | + ) | |
148 | + for index, offset in m.offsets] | |
149 | 149 | |
150 | - # 表情枠 | |
151 | - # type==0はbase | |
152 | - for i, m in enumerate(self.oneSkinMesh.morphList): | |
153 | - if m.type==3: | |
154 | - model.morph_indices.append(i) | |
155 | - for i, m in enumerate(self.oneSkinMesh.morphList): | |
156 | - if m.type==2: | |
157 | - model.morph_indices.append(i) | |
158 | - for i, m in enumerate(self.oneSkinMesh.morphList): | |
159 | - if m.type==1: | |
160 | - model.morph_indices.append(i) | |
161 | - for i, m in enumerate(self.oneSkinMesh.morphList): | |
162 | - if m.type==4: | |
163 | - model.morph_indices.append(i) | |
164 | 150 | |
165 | 151 | # ボーングループ |
166 | - for g in self.skeleton.bone_groups: | |
167 | - name=englishmap.getUnicodeBoneGroupName(g[0]) | |
168 | - if not name: | |
169 | - name=g[0] | |
170 | - englishName=g[0] | |
171 | - | |
172 | - model.bone_group_list.append(pmd.BoneGroup( | |
173 | - (name+'\n').encode('cp932'), | |
174 | - (englishName+'\n').encode('cp932') | |
175 | - )) | |
176 | - | |
177 | - # ボーングループメンバー | |
178 | - for i, b in enumerate(self.skeleton.bones): | |
179 | - if i==0: | |
180 | - continue | |
181 | - if b.type in [6, 7]: | |
182 | - continue | |
183 | - model.bone_display_list.append((i, self.skeleton.getBoneGroup(b))) | |
184 | - | |
185 | - # English | |
186 | - model.english_name=self.englishName.encode('cp932') | |
187 | - model.english_comment=self.englishComment.encode('cp932') | |
188 | - | |
189 | - # toon | |
190 | - toonMeshObject=None | |
191 | - for o in bl.object.each(): | |
192 | - try: | |
193 | - if o.name.startswith(bl.TOON_TEXTURE_OBJECT): | |
194 | - toonMeshObject=o | |
195 | - except: | |
196 | - p(o.name) | |
197 | - break | |
198 | - if toonMeshObject: | |
199 | - toonMesh=bl.object.getData(toonMeshObject) | |
200 | - toonMaterial=bl.mesh.getMaterial(toonMesh, 0) | |
201 | - for i in range(10): | |
202 | - t=bl.material.getTexture(toonMaterial, i) | |
203 | - if t: | |
204 | - model.toon_textures[i]=("%s" % t.name).encode('cp932') | |
205 | - else: | |
206 | - model.toon_textures[i]=("toon%02d.bmp" % (i+1)).encode('cp932') | |
207 | - else: | |
208 | - for i in range(10): | |
209 | - model.toon_textures[i]=("toon%02d.bmp" % (i+1)).encode('cp932') | |
152 | + model.display_slots=[pmx.DisplaySlot( | |
153 | + name=name, | |
154 | + english_name='', | |
155 | + special_flag=0, | |
156 | + ) | |
157 | + for name, members in ex.skeleton.bone_groups] | |
210 | 158 | |
211 | 159 | # rigid body |
212 | 160 | boneNameMap={} |
213 | - for i, b in enumerate(self.skeleton.bones): | |
214 | - boneNameMap[b.name]=b | |
161 | + for i, b in enumerate(ex.skeleton.bones): | |
162 | + boneNameMap[b.name]=i | |
215 | 163 | rigidNameMap={} |
216 | - for i, obj in enumerate(self.oneSkinMesh.rigidbodies): | |
164 | + for i, obj in enumerate(ex.oneSkinMesh.rigidbodies): | |
217 | 165 | name=obj[bl.RIGID_NAME] if bl.RIGID_NAME in obj else obj.name |
218 | 166 | print(name) |
219 | 167 | rigidNameMap[name]=i |
220 | 168 | boneIndex=boneNameMap[obj[bl.RIGID_BONE_NAME]] |
221 | 169 | if boneIndex==0: |
222 | 170 | boneIndex=-1 |
223 | - bone=self.skeleton.bones[0] | |
171 | + bone=ex.skeleton.bones[0] | |
224 | 172 | else: |
225 | - bone=self.skeleton.bones[boneIndex] | |
173 | + bone=ex.skeleton.bones[boneIndex] | |
226 | 174 | if obj[bl.RIGID_SHAPE_TYPE]==0: |
227 | - shape_type=pmd.SHAPE_SPHERE | |
175 | + shape_type=0 | |
228 | 176 | shape_size=common.Vector3(obj.scale[0], 0, 0) |
229 | 177 | elif obj[bl.RIGID_SHAPE_TYPE]==1: |
230 | - shape_type=pmd.SHAPE_BOX | |
178 | + shape_type=1 | |
231 | 179 | shape_size=common.Vector3(obj.scale[0], obj.scale[1], obj.scale[2]) |
232 | 180 | elif obj[bl.RIGID_SHAPE_TYPE]==2: |
233 | - shape_type=pmd.SHAPE_CAPSULE | |
181 | + shape_type=2 | |
234 | 182 | shape_size=common.Vector3(obj.scale[0], obj.scale[2], 0) |
235 | - rigidBody=pmd.RigidBody( | |
236 | - name.encode('cp932'), | |
183 | + rigidBody=pmx.RigidBody( | |
184 | + name=name, | |
185 | + english_name='', | |
237 | 186 | collision_group=obj[bl.RIGID_GROUP], |
238 | 187 | no_collision_group=obj[bl.RIGID_INTERSECTION_GROUP], |
239 | 188 | bone_index=boneIndex, |
@@ -256,9 +205,11 @@ def create_pmx(ex): | ||
256 | 205 | ) |
257 | 206 | model.rigidbodies.append(rigidBody) |
258 | 207 | |
259 | - # constraint | |
260 | - model.joints=[pmd.Joint( | |
261 | - name=obj[bl.CONSTRAINT_NAME].encode('cp932'), | |
208 | + # joint | |
209 | + model.joints=[pmx.Joint( | |
210 | + name=obj[bl.CONSTRAINT_NAME], | |
211 | + english_name='', | |
212 | + joint_type=0, | |
262 | 213 | rigidbody_index_a=rigidNameMap[obj[bl.CONSTRAINT_A]], |
263 | 214 | rigidbody_index_b=rigidNameMap[obj[bl.CONSTRAINT_B]], |
264 | 215 | position=common.Vector3( |
@@ -296,11 +247,9 @@ def create_pmx(ex): | ||
296 | 247 | obj[bl.CONSTRAINT_SPRING_ROT][1], |
297 | 248 | obj[bl.CONSTRAINT_SPRING_ROT][2]) |
298 | 249 | ) |
299 | - for obj in self.oneSkinMesh.constraints] | |
250 | + for obj in ex.oneSkinMesh.constraints] | |
300 | 251 | |
301 | - # 書き込み | |
302 | - bl.message('write: %s' % path) | |
303 | - return writer.write(io.open(path, 'wb'), model) | |
252 | + return model | |
304 | 253 | |
305 | 254 | |
306 | 255 | def _execute(filepath): |
@@ -239,26 +239,9 @@ class OneSkinMesh(object): | ||
239 | 239 | |
240 | 240 | # メッシュのコピーを生成してオブジェクトの行列を適用する |
241 | 241 | copyMesh, copyObj=bl.object.duplicate(obj) |
242 | + copyObj.name="tmp_object" | |
242 | 243 | if len(copyMesh.vertices)>0: |
243 | 244 | # apply transform |
244 | - """ | |
245 | - try: | |
246 | - # svn 36722 | |
247 | - copyObj.scale=obj.scale | |
248 | - bpy.ops.object.transform_apply(scale=True) | |
249 | - copyObj.rotation_euler=obj.rotation_euler | |
250 | - bpy.ops.object.transform_apply(rotation=True) | |
251 | - copyObj.location=obj.location | |
252 | - bpy.ops.object.transform_apply(location=True) | |
253 | - except AttributeError as e: | |
254 | - # 2.57b | |
255 | - copyObj.scale=obj.scale | |
256 | - bpy.ops.object.scale_apply() | |
257 | - copyObj.rotation_euler=obj.rotation_euler | |
258 | - bpy.ops.object.rotation_apply() | |
259 | - copyObj.location=obj.location | |
260 | - bpy.ops.object.location_apply() | |
261 | - """ | |
262 | 245 | copyMesh.transform(obj.matrix_world) |
263 | 246 | |
264 | 247 | # apply modifier |
@@ -20,7 +20,6 @@ def convert_coord(pos): | ||
20 | 20 | def VtoV(v): |
21 | 21 | return bl.createVector(v.x, v.y, v.z) |
22 | 22 | |
23 | -# マテリアル毎にメッシュを作成する | |
24 | 23 | def get_object_name(fmt, index, name): |
25 | 24 | """ |
26 | 25 | object名を作る。最大21バイト |
@@ -297,16 +296,17 @@ def _execute(filepath): | ||
297 | 296 | for pos in (v.position for v in model.vertices)] |
298 | 297 | |
299 | 298 | for i, m in enumerate(model.materials): |
299 | + name=get_object_name("{0:02}:", i, m.name) | |
300 | 300 | #################### |
301 | 301 | # material |
302 | 302 | #################### |
303 | - material=__create_a_material(m, m.name, textures_and_images) | |
303 | + material=__create_a_material(m, name, textures_and_images) | |
304 | 304 | |
305 | 305 | #################### |
306 | 306 | # mesh object |
307 | 307 | #################### |
308 | 308 | # object名はutf-8で21byteまで |
309 | - mesh, mesh_object=bl.mesh.create(get_object_name("{0:02}:", i, m.name)) | |
309 | + mesh, mesh_object=bl.mesh.create(name) | |
310 | 310 | bl.mesh.addMaterial(mesh, material) |
311 | 311 | # activate object |
312 | 312 | bl.object.deselectAll() |