OSDN Git Service

refactoring import_scene_mqo.py
[meshio/meshio.git] / blender25 / import_scene_mqo.py
1 # coding: utf-8
2
3 __author__= ['ousttrue']
4 __url__ = ("")
5 __version__= '0.1'
6 __bpydoc__= '''\
7 mqo Importer
8
9 This script imports a mqo into Blender for editing.
10 '''
11
12 import bpy
13 from bpy.props import *
14 import Mathutils
15 import sys
16 import os
17 from meshio import mqo
18
19
20 SCALING=0.01
21
22
23 def create_materials(mqo, scene, directory):
24     materials = []
25     textureMap={}
26     imageMap={}
27     if len(mqo.materials)>0:
28         for m in mqo.materials:
29             material = bpy.data.materials.new(m.getName())
30             materials.append(material)
31             # mqo material
32             material.diffuse_color=[m.color.r, m.color.g, m.color.b]
33             material.alpha=m.color.a
34             material.diffuse_intensity=m.diffuse
35             texture_name=m.getTexture()
36             if texture_name!='':
37                 if texture_name in textureMap:
38                     texture=textureMap[texture_name]
39                 else:
40                     texture=bpy.data.textures.new(texture_name)
41                     textureMap[m.texture]=texture
42                     texture.type='IMAGE'
43                     texture=texture.recast_type()
44                     texturePath="%s/%s" % (directory, texture_name)
45                     image=bpy.data.add_image(texturePath)
46                     imageMap[m.texture]=image
47                     texture.image=image
48                     texture.mipmap = True
49                     texture.interpolation = True
50                     texture.use_alpha = True
51                 material.add_texture(texture, "UV", ("COLOR", "ALPHA"))
52                 # temporary
53                 material.emit=1.0
54     else:
55         material = bpy.data.materials.new('Default')
56         materials.append(material)
57     return materials, imageMap
58
59 def create_objects(mqo, scene, parent, materials, imageMap):
60     for o in mqo.objects:
61
62         # create mesh
63         mesh=bpy.data.meshes.new("Mesh")
64         meshObject= bpy.data.objects.new(o.name, mesh)
65         scene.objects.link(meshObject)
66         meshObject.parent=parent
67
68         mesh.add_geometry(len(o.vertices), 0, len(o.faces))
69
70         # add vertex
71         unpackedVertices=[]
72         for v in o.vertices:
73             # convert right-handed y-up to right-handed z-up
74             unpackedVertices.extend(
75                     (SCALING*v.x, SCALING*-v.z, SCALING*v.y))
76         mesh.verts.foreach_set("co", unpackedVertices)
77
78         # add face
79         unpackedFaces = []
80         usedMaterial=set()
81         for f in o.faces:
82             face = []
83             for i in range(f.index_count):
84                 face.append(f.getIndex(i))
85
86             if len(face) != 3 and len(face) != 4:
87                 raise RuntimeError(
88                         "{0} vertices in face.".format(len(face)))
89
90             # rotate indices if the 4th is 0
91             if len(face) == 4 and face[3] == 0:
92                 face = [face[3], face[0], face[1], face[2]]
93
94             if len(face) == 3:
95                 face.append(0)
96
97             unpackedFaces.extend(face)
98             usedMaterial.add(f.material_index)
99         mesh.faces.foreach_set("verts_raw", unpackedFaces)
100
101         # add material
102         meshMaterialMap={}
103         materialIndex=0
104         for i in usedMaterial:
105             mesh.add_material(materials[i])
106             meshMaterialMap[i]=materialIndex
107             materialIndex+=1
108
109         # each face
110         mesh.add_uv_texture()
111         for mqo_face, blender_face, uv_face in zip(
112                 o.faces, mesh.faces, mesh.uv_textures[0].data):
113             blender_face.material_index=meshMaterialMap[mqo_face.material_index]
114             if mqo_face.index_count>=3:
115                 uv_face.uv1=[mqo_face.getUV(0).x, 1.0-mqo_face.getUV(0).y]
116                 uv_face.uv2=[mqo_face.getUV(1).x, 1.0-mqo_face.getUV(1).y]
117                 uv_face.uv3=[mqo_face.getUV(2).x, 1.0-mqo_face.getUV(2).y]
118                 if mqo_face.index_count==4:
119                     uv_face.uv4=[
120                             mqo_face.getUV(3).x, 1.0-mqo_face.getUV(3).y]
121             if materials[mqo_face.material_index] in imageMap:
122                 uv_face.image=imageMap[mqo_face.tex]
123                 uv_face.tex=True
124
125         mesh.update()
126
127 def load(filename, context):
128     """
129     load mqo file to context.
130     """
131     io=mqo.IO()
132     if not io.read(filename):
133         return
134
135     scene=context.scene
136
137     # create material
138     materials, imageMap=create_materials(
139             io, scene, os.path.dirname(filename))
140
141     # create group
142     empty=bpy.data.objects.new(os.path.basename(filename), None)
143     scene.objects.link(empty)
144
145     # create mesh
146     create_objects(io, scene, empty, materials, imageMap)
147  
148
149 ###############################################################################
150 # import operator
151 ###############################################################################
152 class IMPORT_OT_mqo(bpy.types.Operator):
153     '''Import from Metasequoia file format (.mqo)'''
154     bl_idname = "import_scene.mqo"
155     bl_label = 'Import MQO'
156
157     # List of operator properties, the attributes will be assigned
158     # to the class instance from the operator settings before calling.
159
160     path = StringProperty(
161             name="File Path", 
162             description="File path used for importing the MQO file", 
163             maxlen= 1024, default= "")
164     filename = StringProperty(
165             name="File Name", 
166             description="Name of the file.")
167     directory = StringProperty(
168             name="Directory", 
169             description="Directory of the file.")
170
171     def execute(self, context):
172         load(self.properties.path, context)
173         return {'FINISHED'}
174
175     def invoke(self, context, event):
176         wm = context.manager
177         wm.add_fileselect(self)
178         return {'RUNNING_MODAL'}
179
180
181 ###############################################################################
182 # register menu
183 ###############################################################################
184 menu_func = lambda self, context: self.layout.operator(
185         IMPORT_OT_mqo.bl_idname, text="Metasequoia (.mqo)")
186
187
188 def register():
189     bpy.types.register(IMPORT_OT_mqo)
190     bpy.types.INFO_MT_file_import.append(menu_func)
191
192 def unregister():
193     bpy.types.unregister(IMPORT_OT_mqo)
194     bpy.types.INFO_MT_file_import.remove(menu_func)
195
196
197 if __name__=="__main__":
198     register()
199