OSDN Git Service

integrate pmd_import for blender25.
[meshio/meshio.git] / swig / blender / bl25.py
1 # coding: utf-8
2 import bpy
3 import mathutils
4
5 import os
6 import time
7 import functools
8
9 ###############################################################################
10 # ProgressBar
11 ###############################################################################
12 class ProgressBar(object):
13     def __init__(self, base):
14         print("#### %s ####" % base)
15         self.base=base
16         self.start=time.time() 
17         self.set('<start>', 0)
18
19     def advance(self, message, progress):
20         self.progress+=float(progress)
21         self._print(message)
22
23     def set(self, message, progress):
24         self.progress=float(progress)
25         self._print(message)
26
27     def _print(self, message):
28         print(message)
29         message="%s: %s" % (self.base, message)
30         #Blender.Window.DrawProgressBar(self.progress, message)
31
32     def finish(self):
33         self.progress=1.0
34         message='finished in %.2f sec' % (time.time()-self.start)
35         self.set(message, 1.0)
36
37
38 ###############################################################################
39 class Writer(object):
40     def __init__(self, path, encoding):
41         self.io=open(path, "wb")
42         self.encoding=encoding
43
44     def write(self, s):
45         self.io.write(s.encode(self.encoding))
46
47     def flush(self):
48         self.io.flush()
49
50     def close(self):
51         self.io.close()
52
53 ###############################################################################
54 def createEmptyObject(scene, name):
55     empty=bpy.data.objects.new(name, None)
56     scene.objects.link(empty)
57     return empty
58
59
60 def createMqoMaterial(m):
61     material = bpy.data.materials.new(m.getName())
62     material.diffuse_color=[m.color.r, m.color.g, m.color.b]
63     material.alpha=m.color.a
64     material.diffuse_intensity=m.diffuse
65     # temporary
66     material.emit=1.0
67     return material
68
69 def createPmdMaterial(m):
70     material = bpy.data.materials.new("Material")
71     material.diffuse_shader='TOON'
72     material.specular_shader='TOON'
73     material.diffuse_color=([m.diffuse.r, m.diffuse.g, m.diffuse.b])
74     material.alpha=m.diffuse.a
75     material.specular_hardness=int(m.shinness)
76     material.specular_color=([m.specular.r, m.specular.g, m.specular.b])
77     material.mirror_color=([m.ambient.r, m.ambient.g, m.ambient.b])
78     material.subsurface_scattering.enabled=True if m.flag==1 else False
79     # temporary
80     material.emit=1.0
81     return material
82
83 def createTexture(path):
84     texture=bpy.data.textures.new(os.path.basename(path))
85     texture.type='IMAGE'
86     texture=texture.recast_type()
87     image=bpy.data.images.load(path)
88     texture.image=image
89     texture.mipmap = True
90     texture.interpolation = True
91     texture.use_alpha = True
92     return texture, image
93
94
95 def materialAddTexture(material, texture):
96     #material.add_texture(texture, "UV", {"COLOR", "ALPHA"})
97     material.add_texture(texture, "UV", "COLOR")
98
99
100 def meshAddMaterial(mesh, material):
101     mesh.add_material(material)
102
103
104 def createMesh(scene, name):
105     mesh=bpy.data.meshes.new("Mesh")
106     mesh_object= bpy.data.objects.new(name, mesh)
107     scene.objects.link(mesh_object)
108     return mesh, mesh_object
109
110
111 def objectMakeParent(parent, child):
112     child.parent=parent
113
114
115 def meshAddMqoGeometry(mesh, o, materials, imageMap, scale):
116     # count triangle and quadrangle
117     faceCount=0
118     for f in o.faces:
119         if f.index_count==3 or f.index_count==4:
120             faceCount+=1
121     mesh.add_geometry(len(o.vertices), 0, faceCount)
122
123     # add vertex
124     unpackedVertices=[]
125     for v in o.vertices:
126         # convert right-handed y-up to right-handed z-up
127         unpackedVertices.extend(
128                 (scale*v.x, scale*-v.z, scale*v.y))
129     mesh.verts.foreach_set("co", unpackedVertices)
130
131     # add face
132     unpackedFaces = []
133     usedMaterial=set()
134
135     def getFace(f):
136         face = []
137         for i in range(f.index_count):
138             face.append(f.getIndex(i))
139         return face
140
141     for f in o.faces:
142         face=getFace(f)
143         if len(face) != 3 and len(face) != 4:
144             print("{0} vertices in face.".format(len(face)))
145             continue
146
147         if len(face) == 4:
148             if face[3] == 0:
149                 # rotate indices if the 4th is 0
150                 face = [face[3], face[0], face[1], face[2]]
151         elif len(face) == 3:
152             if face[2] == 0:
153                 # rotate indices if the 3rd is 0
154                 face = [face[2], face[0], face[1], 0]
155             else:
156                 face.append(0)
157
158         unpackedFaces.extend(face)
159         usedMaterial.add(f.material_index)
160     try:
161         mesh.faces.foreach_set("verts_raw", unpackedFaces)
162     except:
163         #print([getFace(f) for f in o.faces])
164         print("fail to mesh.faces.foreach_set")
165         return
166
167     # add material
168     meshMaterialMap={}
169     materialIndex=0
170     for i in usedMaterial:
171         mesh.add_material(materials[i])
172         meshMaterialMap[i]=materialIndex
173         materialIndex+=1
174
175     # each face
176     mesh.add_uv_texture()
177     for mqo_face, blender_face, uv_face in zip(
178             o.faces, mesh.faces, mesh.uv_textures[0].data):
179         if mqo_face.index_count<3:
180             continue
181         blender_face.material_index=meshMaterialMap[mqo_face.material_index]
182         if mqo_face.index_count>=3:
183             uv_face.uv1=[mqo_face.getUV(0).x, 1.0-mqo_face.getUV(0).y]
184             uv_face.uv2=[mqo_face.getUV(1).x, 1.0-mqo_face.getUV(1).y]
185             uv_face.uv3=[mqo_face.getUV(2).x, 1.0-mqo_face.getUV(2).y]
186             if mqo_face.index_count==4:
187                 uv_face.uv4=[
188                         mqo_face.getUV(3).x, 1.0-mqo_face.getUV(3).y]
189         if materials[mqo_face.material_index] in imageMap:
190             uv_face.image=imageMap[mqo_face.material_index]
191             uv_face.tex=True
192
193     mesh.update()
194
195 def getTexture(m, dirname):
196     tex=""
197     aplane=""
198     # texture
199     for slot in m.texture_slots:
200         if slot and slot.texture:
201             texture=slot.texture
202             if  texture.type=="IMAGE":
203                 image=texture.image
204                 if not image:
205                     continue
206                 imagePath=image.filename
207                 if len(dirname)>0 and imagePath.startswith(dirname):
208                     # \e$BAjBP%Q%9$KJQ49$9$k\e(B
209                     imagePath=imagePath[len(dirname)+1:len(imagePath)]
210                 #imagePath=Blender.sys.expandpath(
211                 #        imagePath).replace("\\", '/')
212                 if slot.map_colordiff:
213                     tex=" tex(\"%s\")" % imagePath
214                 elif slot.map_alpha:
215                     aplane=" aplane(\"%s\")" % imagePath
216     return tex, aplane
217
218 def objectDuplicate(scene, obj):
219     bpy.ops.object.select_all(action='DESELECT')
220     obj.selected=True
221     scene.objects.active=obj
222     bpy.ops.object.duplicate()
223     dumy=scene.objects.active
224     bpy.ops.object.rotation_apply()
225     bpy.ops.object.scale_apply()
226     bpy.ops.object.location_apply()
227     return dumy.data, dumy
228
229 def objectDelete(scene, obj):
230     scene.objects.unlink(obj)
231
232 def faceVertexCount(face):
233     return len(face.verts)
234
235 def faceVertices(face):
236     return face.verts[:]
237
238 def meshHasUV(mesh):
239     return mesh.active_uv_texture
240
241 def faceHasUV(mesh, i, face):
242     return mesh.active_uv_texture.data[i]
243
244 def faceGetUV(mesh, i, faces, count):
245     uvFace=mesh.active_uv_texture.data[i]
246     if count==3:
247         return (uvFace.uv1, uvFace.uv2, uvFace.uv3)
248     elif count==4:
249         return (uvFace.uv1, uvFace.uv2, uvFace.uv3, uvFace.uv4)
250     else:
251         print(count)
252         assert(False)
253
254 def materialToMqo(m):
255     return "\"%s\" shader(3) col(%f %f %f %f)" % (
256             m.name, 
257             m.diffuse_color[0], m.diffuse_color[1], m.diffuse_color[2], 
258             m.alpha)
259
260 def faceMaterialIndex(face):
261     return face.material_index
262
263 def objectGetData(o):
264     return o.data
265
266 def objectAddArmatureModifier(o, armature_object):
267     mod=o.modifiers.new("Modifier", "ARMATURE")
268     mod.object = armature_object
269     mod.use_bone_envelopes=False
270
271 def objectSelect(o):
272     o.selected=True
273
274 def objectGetPose(o):
275     return o.pose
276
277 def poseBoneLimit(n, b):
278     if n.endswith("_t"):
279         return
280     if n.startswith("knee_"):
281         b.ik_dof_y=False
282         b.ik_dof_z=False
283         b.ik_dof_x=True
284         b.ik_limit_x=True
285         b.ik_min_x=0
286         b.ik_max_x=180
287     elif n.startswith("ankle_"):
288         #b.ik_dof_y=False
289         pass
290
291 def enterEditMode():
292     bpy.ops.object.mode_set(mode='EDIT', toggle=False)
293
294 def exitEditMode():
295     bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
296
297 def objectDeselectAll():
298     bpy.ops.object.select_all(action='DESELECT')
299
300 def objectActivate(scene, o):
301     o.selected=True 
302     scene.objects.active=o
303
304 def meshAddVertexGroup(meshObject, name):
305     meshObject.add_vertex_group(name)
306
307 def vertexSetNormal(mvert, normal):
308     mvert.normal=mathutils.Vector(normal)
309
310 def meshUseVertexUv(mesh):
311     pass
312
313 def vertexSetUv(mvert, uv):
314     pass
315
316 def meshAssignVertexGroup(meshObject, name, index, weight):
317     meshObject.add_vertex_to_group(index, 
318                 meshObject.vertex_groups[name], weight, 'ADD')
319
320 def meshCreateVerteicesAndFaces(mesh, vertices, faces):
321     vertexCount=int(len(vertices)/3)
322     faceCount=int(len(faces)/4)
323     mesh.add_geometry(vertexCount, 0, faceCount)
324     mesh.verts.foreach_set("co", vertices)
325     mesh.faces.foreach_set("verts_raw", faces)
326     assert(len(mesh.verts)==vertexCount)
327
328 def meshAddUV(mesh):
329     mesh.add_uv_texture()
330
331 def meshVertsDelete(mesh, remove_vertices):
332     enterEditMode()
333     bpy.ops.mesh.select_all(action='DESELECT')
334     for i in remove_vertices:
335         mesh.verts[i].selected=True
336     bpy.ops.mesh.delete(type='VERT')
337     exitEditMode()
338
339 def createArmature(scene):
340     armature = bpy.data.armatures.new('Armature')
341     armature_object=bpy.data.objects.new('Armature', armature)
342     scene.objects.link(armature_object)
343
344     armature_object.x_ray=True
345     armature.draw_names=True
346     armature.drawtype='OCTAHEDRAL'
347     armature.deform_envelope=False
348     armature.deform_vertexgroups=True
349     armature.x_axis_mirror=True
350
351     return armature, armature_object
352
353 def armatureMakeEditable(scene, armature_object):
354     # select only armature object and set edit mode
355     scene.objects.active=armature_object
356     bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
357     bpy.ops.object.mode_set(mode='EDIT', toggle=False)
358
359 def createIkConstraint(armature_object, p_bone, effector_name, ik):
360     constraint = p_bone.constraints.new('IK')
361     constraint.chain_length=len(ik.children)
362     constraint.target=armature_object
363     constraint.subtarget=effector_name
364     constraint.use_tail=False
365     return constraint
366
367 def createArmatureBone(armature, name):
368     return armature.edit_bones.new(name)
369
370 def boneSetConnected(bone):
371     bone.connected=True
372
373 def createVector(x, y, z):
374     return mathutils.Vector([x, y, z])
375
376 def armatureUpdate(armature):
377     pass
378
379 def boneLayerMask(bone, layers):
380     layer=[]
381     for i in range(32):
382         try:
383             layer.append(True if layers[i]!=0 else False)
384         except IndexError:
385             layer.append(False)
386     bone.layer=layer
387
388 def objectPinShape(o):
389     o.shape_key_lock=True
390
391 def objectAddShapeKey(o, name):
392     return o.add_shape_key(name)
393
394 def objectActivateShapeKey(o, index):
395     o.active_shape_key_index=index
396
397 def shapeKeyAssign(shapeKey, index, pos):
398     shapeKey.data[index].co=pos
399
400 def objectIsVisible(obj):
401     return obj.restrict_view
402
403 def meshVertexGroupNames(meshObject):
404     for g in meshObject.vertex_groups:
405         yield g.name
406
407 def faceNormal(face):
408     return face.normal
409
410 def meshFaceUv(mesh, i, face):
411     return mesh.uv_textures[0].data[i].uv
412
413 def armatureModifierGetObject(m):
414     return m.object
415
416 def objectHasShapeKey(o):
417     return o.data.shape_keys
418
419 def objectShapeKeys(o):
420     return o.data.shape_keys.keys
421
422 def meshVertexGroup(meshObject, name):
423     for i, v in enumerate(meshObject.data.verts):
424         for g in v.groups:
425             if meshObject.vertex_groups[g.group].name==name:
426                 yield(i)
427
428 def materialGet(scene, material_name):
429     return bpy.data.materials[material_name]
430