3 Name: 'Metasequoia(.mqo)...'
\r
6 Tooltip: 'Import from Metasequoia file format (.mqo)'
\r
8 __author__= 'ousttrue'
\r
9 __url__ = ["http://gunload.web.fc2.com/blender/"]
\r
10 __version__= '0.4 2009/11/25'
\r
15 This script imports a mqo file.
\r
17 0.2 20080123: update.
\r
18 0.3 20091125: modify for linux.
\r
19 0.4 20100310: rewrite.
\r
20 0.5 20100311: create armature from mikoto bone.
\r
29 __slots__=['r', 'g', 'b', 'a']
\r
30 def __init__(self, r=0, g=0, b=0, a=0):
\r
36 class Vector3(object):
\r
37 __slots__=['x', 'y', 'z']
\r
38 def __init__(self, x=0, y=0, z=0):
\r
44 return "[%f, %f, %f]" % (self.x, self.y, self.z)
\r
46 def __sub__(self, rhs):
\r
47 return Vector3(self.x-rhs.x, self.y-rhs.y, self.z-rhs.z)
\r
49 def getSqNorm(self):
\r
50 return self.x*self.x + self.y*self.y + self.z*self.z
\r
53 return math.sqrt(self.getSqNorm())
\r
55 def normalize(self):
\r
56 factor=1.0/self.getNorm()
\r
63 return [self.x, self.y, self.z]
\r
67 return lhs.x*rhs.x + lhs.y*rhs.y + lhs.z*rhs.z
\r
70 def cross(lhs, rhs):
\r
72 lhs.y*rhs.z - rhs.y*lhs.z,
\r
73 lhs.z*rhs.x - rhs.z*lhs.x,
\r
74 lhs.x*rhs.y - rhs.x*lhs.y,
\r
78 class Vector2(object):
\r
79 __slots__=['x', 'y']
\r
80 def __init__(self, x=0, y=0):
\r
85 return "[%f, %f]" % (self.x, self.y)
\r
87 def __sub__(self, rhs):
\r
88 return Vector3(self.x-rhs.x, self.y-rhs.y)
\r
91 def cross(lhs, rhs):
\r
92 return lhs.x*rhs.y-lhs.y*rhs.x
\r
95 ###############################################################################
\r
97 ###############################################################################
\r
98 class Material(object):
\r
100 "name", "shader", "color", "diffuse",
\r
101 "ambient", "emit", "specular", "power",
\r
104 def __init__(self, name):
\r
107 self.color=RGBA(0.5, 0.5, 0.5, 1.0)
\r
115 def getName(self): return self.name
\r
116 def getTexture(self): return self.tex
\r
118 def parse(self, line):
\r
121 leftParenthesis=line.find("(", offset)
\r
122 if leftParenthesis==-1:
\r
124 key=line[offset:leftParenthesis]
\r
125 rightParenthesis=line.find(")", leftParenthesis+1)
\r
126 if rightParenthesis==-1:
\r
127 raise ValueError("assert")
\r
129 param=line[leftParenthesis+1:rightParenthesis]
\r
131 self.shader=int(param)
\r
133 self.color=RGBA(*[float(e) for e in param.split()])
\r
135 self.diffuse=float(param)
\r
137 self.ambient=float(param)
\r
139 self.emit=float(param)
\r
141 self.specular=float(param)
\r
143 self.power=float(param)
\r
145 self.tex=param[1:-1]
\r
148 "%s#parse" % self.name,
\r
149 "unknown key: %s" % key
\r
152 offset=rightParenthesis+2
\r
155 return "<Material %s shader: %d [%f, %f, %f, %f] %f>" % (
\r
156 self.name, self.shader,
\r
157 self.color[0], self.color[1], self.color[2], self.color[3],
\r
162 __slots__=["name", "depth", "folding",
\r
163 "scale", "rotation", "translation",
\r
164 "visible", "locking", "shading", "facet",
\r
165 "color", "color_type", "mirror", "mirror_axis",
\r
166 "vertices", "faces", "edges", "smoothing",
\r
169 def __init__(self, name):
\r
176 self.scale=[1, 1, 1]
\r
177 self.rotation=[0, 0, 0]
\r
178 self.translation=[0, 0, 0]
\r
183 self.color=[1, 1, 1]
\r
188 def getName(self): return self.name
\r
190 def addVertex(self, x, y, z):
\r
191 self.vertices.append(Vector3(x, y, z))
\r
193 def addFace(self, face):
\r
194 if face.index_count==2:
\r
195 self.edges.append(face)
\r
197 self.faces.append(face)
\r
200 return "<Object %s, %d vertices, %d faces>" % (
\r
201 self.name, len(self.vertices), len(self.faces))
\r
204 class Face(object):
\r
207 "indices", "material_index", "col", "uv",
\r
209 def __init__(self, index_count, line):
\r
210 if index_count<2 or index_count>4:
\r
211 raise ValueError("invalid vertex count: %d" % index_count)
\r
212 self.material_index=0
\r
214 self.uv=[Vector2(0, 0)]*4
\r
215 self.index_count=index_count
\r
218 leftParenthesis=line.find("(", offset)
\r
219 if leftParenthesis==-1:
\r
221 key=line[offset:leftParenthesis]
\r
222 rightParenthesis=line.find(")", leftParenthesis+1)
\r
223 if rightParenthesis==-1:
\r
224 raise ValueError("assert")
\r
225 params=line[leftParenthesis+1:rightParenthesis].split()
\r
227 self.indices=[int(e) for e in params]
\r
229 self.material_index=int(params[0])
\r
231 uv_list=[float(e) for e in params]
\r
233 for i in range(0, len(uv_list), 2):
\r
234 self.uv.append(Vector2(uv_list[i], uv_list[i+1]))
\r
239 d, m=divmod(d, 256)
\r
242 d, m=divmod(d, 256)
\r
245 d, m=divmod(d, 256)
\r
248 d, m=divmod(d, 256)
\r
251 print("Face#__init__:unknown key: %s" % key)
\r
253 offset=rightParenthesis+2
\r
255 def getIndex(self, i): return self.indices[i]
\r
256 def getUV(self, i): return self.uv[i] if i<len(self.uv) else Vector2(0, 0)
\r
259 def withio(method):
\r
260 def new(self, path):
\r
261 self.io=open(path, encoding='cp932')
\r
262 result=method(self)
\r
271 "eof", "io", "lines",
\r
272 "materials", "objects",
\r
274 def __init__(self):
\r
275 self.has_mikoto=False
\r
283 return "<MQO %d lines, %d materials, %d objects>" % (
\r
284 self.lines, len(self.materials), len(self.objects))
\r
287 line=self.io.readline()
\r
292 return line.strip()
\r
294 def printError(self, method, msg):
\r
295 print("%s:%s:%d" % (method, msg, self.lines))
\r
299 line=self.getline()
\r
300 if line!="Metasequoia Document":
\r
301 print("invalid signature")
\r
304 line=self.getline()
\r
305 if line!="Format Text Ver 1.0":
\r
306 print("unknown version: %s" % line)
\r
309 line=self.getline()
\r
317 tokens=line.split()
\r
323 if not self.readChunk():
\r
325 elif key=="Material":
\r
326 if not self.readMaterial():
\r
328 elif key=="Object":
\r
329 firstQuote=line.find('"')
\r
330 secondQuote=line.find('"', firstQuote+1)
\r
331 if not self.readObject(line[firstQuote+1:secondQuote]):
\r
333 elif key=="BackImage":
\r
334 if not self.readChunk():
\r
336 elif key=="IncludeXml":
\r
337 firstQuote=line.find('"')
\r
338 secondQuote=line.find('"', firstQuote+1)
\r
339 print("IncludeXml", line[firstQuote+1:secondQuote])
\r
341 print("unknown key: %s" % key)
\r
342 if not self.readChunk():
\r
345 self.printError("parse", "invalid eof")
\r
348 def readObject(self, name):
\r
350 if name.startswith('bone'):
\r
351 self.has_mikoto=True
\r
352 self.objects.append(obj)
\r
354 line=self.getline()
\r
365 tokens=line.split()
\r
368 if not self.readVertex(obj):
\r
371 if not self.readFace(obj):
\r
374 obj.depth=int(tokens[1])
\r
377 "%s#readObject" % name,
\r
378 "unknown key: %s" % name
\r
381 self.printError("readObject", "invalid eof")
\r
384 def readFace(self, obj):
\r
386 line=self.getline()
\r
398 tokens=line.split(' ', 1)
\r
400 obj.addFace(Face(int(tokens[0]), tokens[1]))
\r
401 except ValueError as ex:
\r
402 self.printError("readFace", ex)
\r
405 self.printError("readFace", "invalid eof")
\r
408 def readVertex(self, obj):
\r
410 line=self.getline()
\r
422 obj.addVertex(*[float(v) for v in line.split()])
\r
424 self.printError("readVertex", "invalid eof")
\r
427 def readMaterial(self):
\r
429 line=self.getline()
\r
441 secondQuaote=line.find('"', 1)
\r
442 material=Material(line[1:secondQuaote])
\r
444 material.parse(line[secondQuaote+2:])
\r
445 except ValueError as ex:
\r
446 self.printError("readMaterial", ex)
\r
448 self.materials.append(material)
\r
450 self.printError("readMaterial", "invalid eof")
\r
453 def readChunk(self):
\r
456 line=self.getline()
\r
468 elif line.find("{")!=-1:
\r
471 self.printError("readChunk", "invalid eof")
\r