4 http://www.metaseq.net/metaseq/format.html
\r
14 __slots__=['r', 'g', 'b', 'a']
\r
15 def __init__(self, r=0, g=0, b=0, a=0):
\r
21 def __getitem__(self, key):
\r
34 class Vector3(object):
\r
36 __slots__=['x', 'y', 'z']
\r
37 def __init__(self, x=0, y=0, z=0):
\r
43 return "[%f, %f, %f]" % (self.x, self.y, self.z)
\r
45 def __sub__(self, rhs):
\r
46 return Vector3(self.x-rhs.x, self.y-rhs.y, self.z-rhs.z)
\r
48 def getSqNorm(self):
\r
49 return self.x*self.x + self.y*self.y + self.z*self.z
\r
52 return math.sqrt(self.getSqNorm())
\r
54 def normalize(self):
\r
55 factor=1.0/self.getNorm()
\r
62 return [self.x, self.y, self.z]
\r
66 """dot(inner) product"""
\r
67 return lhs.x*rhs.x + lhs.y*rhs.y + lhs.z*rhs.z
\r
70 def cross(lhs, rhs):
\r
71 """cross(outer) product"""
\r
73 lhs.y*rhs.z - rhs.y*lhs.z,
\r
74 lhs.z*rhs.x - rhs.z*lhs.x,
\r
75 lhs.x*rhs.y - rhs.x*lhs.y,
\r
79 class Vector2(object):
\r
81 __slots__=['x', 'y']
\r
82 def __init__(self, x=0, y=0):
\r
87 return "[%f, %f]" % (self.x, self.y)
\r
89 def __sub__(self, rhs):
\r
90 return Vector3(self.x-rhs.x, self.y-rhs.y)
\r
93 def cross(lhs, rhs):
\r
94 """cross(outer) product"""
\r
95 return lhs.x*rhs.y-lhs.y*rhs.x
\r
101 class Material(object):
\r
113 tex: cp932 windows file path
\r
116 "name", "shader", "color", "diffuse",
\r
117 "ambient", "emit", "specular", "power",
\r
120 def __init__(self, name):
\r
123 self.color=RGBA(0.5, 0.5, 0.5, 1.0)
\r
131 def getName(self): return self.name
\r
132 def getTexture(self): return self.tex
\r
134 def parse(self, line):
\r
137 leftParenthesis=line.find("(", offset)
\r
138 if leftParenthesis==-1:
\r
140 key=line[offset:leftParenthesis]
\r
141 rightParenthesis=line.find(")", leftParenthesis+1)
\r
142 if rightParenthesis==-1:
\r
143 raise ValueError("assert")
\r
145 param=line[leftParenthesis+1:rightParenthesis]
\r
147 self.shader=int(param)
\r
149 self.color=RGBA(*[float(e) for e in param.split()])
\r
151 self.diffuse=float(param)
\r
153 self.ambient=float(param)
\r
155 self.emit=float(param)
\r
157 self.specular=float(param)
\r
159 self.power=float(param)
\r
161 self.tex=param[1:-1]
\r
164 "%s#parse" % self.name,
\r
165 "unknown key: %s" % key
\r
168 offset=rightParenthesis+2
\r
171 return "<Material %s shader: %d [%f, %f, %f, %f] %f>" % (
\r
172 self.name, self.shader,
\r
173 self.color[0], self.color[1], self.color[2], self.color[3],
\r
182 depth: object hierarchy
\r
190 facet: smoothing threshold
\r
200 __slots__=["name", "depth", "folding",
\r
201 "scale", "rotation", "translation",
\r
202 "visible", "locking", "shading", "facet",
\r
203 "color", "color_type", "mirror", "mirror_axis",
\r
204 "vertices", "faces", "edges", "smoothing",
\r
207 def __init__(self, name):
\r
214 self.scale=[1, 1, 1]
\r
215 self.rotation=[0, 0, 0]
\r
216 self.translation=[0, 0, 0]
\r
221 self.color=[1, 1, 1]
\r
226 def getName(self): return self.name
\r
228 def addVertex(self, x, y, z):
\r
229 self.vertices.append(Vector3(x, y, z))
\r
231 def addFace(self, face):
\r
232 if face.index_count==2:
\r
233 self.edges.append(face)
\r
235 self.faces.append(face)
\r
238 return "<Object %s, %d vertices, %d faces>" % (
\r
239 self.name, len(self.vertices), len(self.faces))
\r
242 class Face(object):
\r
246 index_count: 2 or 3 or 4
\r
247 indices: index x index_count
\r
249 col: vertex_color x index_count
\r
250 uv: Vector2 x index_count
\r
254 "indices", "material_index", "col", "uv",
\r
256 def __init__(self, index_count, line):
\r
257 if index_count<2 or index_count>4:
\r
258 raise ValueError("invalid vertex count: %d" % index_count)
\r
259 self.material_index=0
\r
261 self.uv=[Vector2(0, 0)]*4
\r
262 self.index_count=index_count
\r
265 leftParenthesis=line.find("(", offset)
\r
266 if leftParenthesis==-1:
\r
268 key=line[offset:leftParenthesis]
\r
269 rightParenthesis=line.find(")", leftParenthesis+1)
\r
270 if rightParenthesis==-1:
\r
271 raise ValueError("assert")
\r
272 params=line[leftParenthesis+1:rightParenthesis].split()
\r
274 self.indices=[int(e) for e in params]
\r
276 self.material_index=int(params[0])
\r
278 uv_list=[float(e) for e in params]
\r
280 for i in range(0, len(uv_list), 2):
\r
281 self.uv.append(Vector2(uv_list[i], uv_list[i+1]))
\r
286 d, m=divmod(d, 256)
\r
289 d, m=divmod(d, 256)
\r
292 d, m=divmod(d, 256)
\r
295 d, m=divmod(d, 256)
\r
298 print("Face#__init__:unknown key: %s" % key)
\r
300 offset=rightParenthesis+2
\r
302 def getIndex(self, i): return self.indices[i]
\r
303 def getUV(self, i): return self.uv[i] if i<len(self.uv) else Vector2(0, 0)
\r
306 def withio(method):
\r
307 def new(self, path):
\r
308 print(sys.version_info[0])
\r
309 if sys.version_info[0]<3:
\r
312 self.io=open(path, encoding='cp932')
\r
313 result=method(self)
\r
325 "eof", "io", "lines",
\r
326 "materials", "objects",
\r
328 def __init__(self):
\r
329 self.has_mikoto=False
\r
337 return "<MQO %d lines, %d materials, %d objects>" % (
\r
338 self.lines, len(self.materials), len(self.objects))
\r
341 line=self.io.readline()
\r
346 return line.strip()
\r
348 def printError(self, method, msg):
\r
349 print("%s:%s:%d" % (method, msg, self.lines))
\r
353 line=self.getline()
\r
354 if line!="Metasequoia Document":
\r
355 print("invalid signature")
\r
358 line=self.getline()
\r
359 if line!="Format Text Ver 1.0":
\r
360 print("unknown version: %s" % line)
\r
363 line=self.getline()
\r
371 tokens=line.split()
\r
377 if not self.readChunk():
\r
379 elif key=="Material":
\r
380 if not self.readMaterial():
\r
382 elif key=="Object":
\r
383 firstQuote=line.find('"')
\r
384 secondQuote=line.find('"', firstQuote+1)
\r
385 if not self.readObject(line[firstQuote+1:secondQuote]):
\r
387 elif key=="BackImage":
\r
388 if not self.readChunk():
\r
390 elif key=="IncludeXml":
\r
391 firstQuote=line.find('"')
\r
392 secondQuote=line.find('"', firstQuote+1)
\r
393 print("IncludeXml", line[firstQuote+1:secondQuote])
\r
395 print("unknown key: %s" % key)
\r
396 if not self.readChunk():
\r
399 self.printError("parse", "invalid eof")
\r
402 def readObject(self, name):
\r
404 if name.startswith('bone'):
\r
405 self.has_mikoto=True
\r
406 self.objects.append(obj)
\r
408 line=self.getline()
\r
419 tokens=line.split()
\r
422 if not self.readVertex(obj):
\r
425 if not self.readFace(obj):
\r
428 obj.depth=int(tokens[1])
\r
431 "%s#readObject" % name,
\r
432 "unknown key: %s" % key
\r
435 self.printError("readObject", "invalid eof")
\r
438 def readFace(self, obj):
\r
440 line=self.getline()
\r
452 tokens=line.split(' ', 1)
\r
454 obj.addFace(Face(int(tokens[0]), tokens[1]))
\r
455 except ValueError as ex:
\r
456 self.printError("readFace", ex)
\r
459 self.printError("readFace", "invalid eof")
\r
462 def readVertex(self, obj):
\r
464 line=self.getline()
\r
476 obj.addVertex(*[float(v) for v in line.split()])
\r
478 self.printError("readVertex", "invalid eof")
\r
481 def readMaterial(self):
\r
483 line=self.getline()
\r
495 secondQuaote=line.find('"', 1)
\r
496 material=Material(line[1:secondQuaote])
\r
498 material.parse(line[secondQuaote+2:])
\r
499 except ValueError as ex:
\r
500 self.printError("readMaterial", ex)
\r
502 self.materials.append(material)
\r
504 self.printError("readMaterial", "invalid eof")
\r
507 def readChunk(self):
\r
510 line=self.getline()
\r
522 elif line.find("{")!=-1:
\r
525 self.printError("readChunk", "invalid eof")
\r