OSDN Git Service

refactoring.
[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     # temporary
79     material.emit=1.0
80     return material
81
82 def createTexture(path):
83     texture=bpy.data.textures.new(os.path.basename(path))
84     texture.type='IMAGE'
85     texture=texture.recast_type()
86     image=bpy.data.images.load(path)
87     texture.image=image
88     texture.mipmap = True
89     texture.interpolation = True
90     texture.use_alpha = True
91     return texture, image
92
93
94 def materialAddTexture(material, texture):
95     #material.add_texture(texture, "UV", {"COLOR", "ALPHA"})
96     material.add_texture(texture, "UV", "COLOR")
97
98
99 def meshAddMaterial(mesh, material):
100     mesh.add_material(material)
101
102
103 def createMesh(scene, name):
104     mesh=bpy.data.meshes.new("Mesh")
105     mesh_object= bpy.data.objects.new(name, mesh)
106     scene.objects.link(mesh_object)
107     return mesh, mesh_object
108
109
110 def objectMakeParent(parent, child):
111     child.parent=parent
112
113
114 def meshAddMqoGeometry(mesh, o, materials, imageMap, scale):
115     # count triangle and quadrangle
116     faceCount=0
117     for f in o.faces:
118         if f.index_count==3 or f.index_count==4:
119             faceCount+=1
120     mesh.add_geometry(len(o.vertices), 0, faceCount)
121
122     # add vertex
123     unpackedVertices=[]
124     for v in o.vertices:
125         # convert right-handed y-up to right-handed z-up
126         unpackedVertices.extend(
127                 (scale*v.x, scale*-v.z, scale*v.y))
128     mesh.verts.foreach_set("co", unpackedVertices)
129
130     # add face
131     unpackedFaces = []
132     usedMaterial=set()
133
134     def getFace(f):
135         face = []
136         for i in range(f.index_count):
137             face.append(f.getIndex(i))
138         return face
139
140     for f in o.faces:
141         face=getFace(f)
142         if len(face) != 3 and len(face) != 4:
143             print("{0} vertices in face.".format(len(face)))
144             continue
145
146         if len(face) == 4:
147             if face[3] == 0:
148                 # rotate indices if the 4th is 0
149                 face = [face[3], face[0], face[1], face[2]]
150         elif len(face) == 3:
151             if face[2] == 0:
152                 # rotate indices if the 3rd is 0
153                 face = [face[2], face[0], face[1], 0]
154             else:
155                 face.append(0)
156
157         unpackedFaces.extend(face)
158         usedMaterial.add(f.material_index)
159     try:
160         mesh.faces.foreach_set("verts_raw", unpackedFaces)
161     except:
162         #print([getFace(f) for f in o.faces])
163         print("fail to mesh.faces.foreach_set")
164         return
165
166     # add material
167     meshMaterialMap={}
168     materialIndex=0
169     for i in usedMaterial:
170         mesh.add_material(materials[i])
171         meshMaterialMap[i]=materialIndex
172         materialIndex+=1
173
174     # each face
175     mesh.add_uv_texture()
176     for mqo_face, blender_face, uv_face in zip(
177             o.faces, mesh.faces, mesh.uv_textures[0].data):
178         if mqo_face.index_count<3:
179             continue
180         blender_face.material_index=meshMaterialMap[mqo_face.material_index]
181         if mqo_face.index_count>=3:
182             uv_face.uv1=[mqo_face.getUV(0).x, 1.0-mqo_face.getUV(0).y]
183             uv_face.uv2=[mqo_face.getUV(1).x, 1.0-mqo_face.getUV(1).y]
184             uv_face.uv3=[mqo_face.getUV(2).x, 1.0-mqo_face.getUV(2).y]
185             if mqo_face.index_count==4:
186                 uv_face.uv4=[
187                         mqo_face.getUV(3).x, 1.0-mqo_face.getUV(3).y]
188         if materials[mqo_face.material_index] in imageMap:
189             uv_face.image=imageMap[mqo_face.material_index]
190             uv_face.tex=True
191
192     mesh.update()
193
194 def getTexture(m, dirname):
195     tex=""
196     aplane=""
197     # texture
198     for slot in m.texture_slots:
199         if slot and slot.texture:
200             texture=slot.texture
201             if  texture.type=="IMAGE":
202                 image=texture.image
203                 if not image:
204                     continue
205                 imagePath=image.filename
206                 if len(dirname)>0 and imagePath.startswith(dirname):
207                     # \e$BAjBP%Q%9$KJQ49$9$k\e(B
208                     imagePath=imagePath[len(dirname)+1:len(imagePath)]
209                 #imagePath=Blender.sys.expandpath(
210                 #        imagePath).replace("\\", '/')
211                 if slot.map_colordiff:
212                     tex=" tex(\"%s\")" % imagePath
213                 elif slot.map_alpha:
214                     aplane=" aplane(\"%s\")" % imagePath
215     return tex, aplane
216
217 def objectDuplicate(scene, obj):
218     bpy.ops.object.select_all(action='DESELECT')
219     obj.selected=True
220     scene.objects.active=obj
221     bpy.ops.object.duplicate()
222     dumy=scene.objects.active
223     bpy.ops.object.rotation_apply()
224     bpy.ops.object.scale_apply()
225     bpy.ops.object.location_apply()
226     return dumy.data, dumy
227
228 def faceVertexCount(face):
229     return len(face.verts)
230
231 def faceVertices(face):
232     return face.verts[:]
233
234 def meshHasUV(mesh):
235     return mesh.active_uv_texture
236
237 def faceHasUV(mesh, i, face):
238     return mesh.active_uv_texture.data[i]
239
240 def faceGetUV(mesh, i, faces, count):
241     uvFace=mesh.active_uv_texture.data[i]
242     if count==3:
243         return (uvFace.uv1, uvFace.uv2, uvFace.uv3)
244     elif count==4:
245         return (uvFace.uv1, uvFace.uv2, uvFace.uv3, uvFace.uv4)
246     else:
247         print(count)
248         assert(False)
249
250 def materialToMqo(m):
251     return "\"%s\" shader(3) col(%f %f %f %f)" % (
252             m.name, 
253             m.diffuse_color[0], m.diffuse_color[1], m.diffuse_color[2], 
254             m.alpha)
255
256 def faceMaterialIndex(face):
257     return face.material_index
258
259 def objectGetData(o):
260     return o.data
261
262 def objectAddArmatureModifier(o, armature_object):
263     mod=o.modifiers.new("Modifier", "ARMATURE")
264     mod.object = armature_object
265     mod.use_bone_envelopes=False
266
267 def objectSelect(o):
268     o.selected=True
269
270 def objectGetPose(o):
271     return o.pose
272
273 def poseBoneLimit(n, b):
274     if n.endswith("_t"):
275         return
276     if n.startswith("knee_"):
277         b.lock_rotation[1]=True
278         b.lock_rotation[2]=True
279         b.ik_min_x=0
280         b.ik_max_x=180
281     elif n.startswith("ankle_"):
282         b.lock_rotation[1]=True
283
284 def enterEditMode():
285     bpy.ops.object.mode_set(mode='EDIT', toggle=False)
286
287 def exitEditMode():
288     bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
289
290 def objectDeselectAll():
291     bpy.ops.object.select_all(action='DESELECT')
292
293 def objectActivate(scene, o):
294     o.selected=True 
295     scene.objects.active=o
296
297 def meshAddVertexGroup(meshObject, name):
298     meshObject.add_vertex_group(name)
299
300 def vertexSetNormal(mvert, normal):
301     mvert.normal=mathutils.Vector(normal)
302
303 def meshUseVertexUv(mesh):
304     pass
305
306 def vertexSetUv(mvert, uv):
307     pass
308
309 def meshAssignVertexGroup(meshObject, name, index, weight):
310     meshObject.add_vertex_to_group(index, 
311                 meshObject.vertex_groups[name], weight, 'ADD')
312
313 def meshCreateVerteicesAndFaces(mesh, vertices, faces):
314     vertexCount=int(len(vertices)/3)
315     faceCount=int(len(faces)/4)
316     mesh.add_geometry(vertexCount, 0, faceCount)
317     mesh.verts.foreach_set("co", vertices)
318     mesh.faces.foreach_set("verts_raw", faces)
319     assert(len(mesh.verts)==vertexCount)
320
321 def meshAddUV(mesh):
322     mesh.add_uv_texture()
323
324 def meshVertsDelete(mesh, remove_vertices):
325     enterEditMode()
326     bpy.ops.mesh.select_all(action='DESELECT')
327     for i in remove_vertices:
328         mesh.verts[i].selected=True
329     bpy.ops.mesh.delete(type='VERT')
330     exitEditMode()
331
332 def createArmature(scene):
333     armature = bpy.data.armatures.new('Armature')
334     armature_object=bpy.data.objects.new('Armature', armature)
335     scene.objects.link(armature_object)
336
337     armature_object.x_ray=True
338     armature.draw_names=True
339     armature.drawtype='OCTAHEDRAL'
340     armature.deform_envelope=False
341     armature.deform_vertexgroups=True
342     armature.x_axis_mirror=True
343
344     return armature, armature_object
345
346 def armatureMakeEditable(scene, armature_object):
347     # select only armature object and set edit mode
348     scene.objects.active=armature_object
349     bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
350     bpy.ops.object.mode_set(mode='EDIT', toggle=False)
351
352 def createIkConstraint(armature_object, p_bone, effector_name, ik):
353     constraint = p_bone.constraints.new('IK')
354     constraint.chain_length=len(ik.children)
355     constraint.target=armature_object
356     constraint.subtarget=effector_name
357     constraint.use_tail=False
358     return constraint
359
360 def createArmatureBone(armature, name):
361     return armature.edit_bones.new(name)
362
363 def boneSetConnected(bone):
364     bone.connected=True
365
366 def createVector(x, y, z):
367     return mathutils.Vector([x, y, z])
368
369 def armatureUpdate(armature):
370     pass
371
372 def boneLayerMask(bone, mask):
373     for i, enable in enumerate(mask):
374         bone.layer[i]=True if enable else False 
375