#!/usr/bin/python
# coding: utf-8
"""
-20091202: VPD読み込みを追加
-20100318: PMD書き込みを追加
-20100731: meshioと互換になるように改造
+utitlities for pmd and vmd loading.
-VMDの読み込み
-http://yumin3123.at.webry.info/200810/article_4.html
-http://atupdate.web.fc2.com/vmd_format.htm
+- python2 and python3 compatibility.
+- common structures.
-PMDの読み込み
-http://blog.goo.ne.jp/torisu_tetosuki/e/209ad341d3ece2b1b4df24abf619d6e4
-
-VPDの読み込み
-
-ToDo:
- rigdid bodies
- constraints
"""
import sys
import codecs
import struct
import math
import re
-#import numpy
from decimal import *
ENCODING='cp932'
+"""
+utility functions for python2 and python3 compatibility.
+"""
if sys.version_info[0]>=3:
xrange=range
-###############################################################################
-# utility
-###############################################################################
if sys.version_info[0]<3:
def truncate_zero(src):
"""
- 0x00以降を捨てる
+ drop after 0x00
"""
assert(type(src)==bytes)
pos = src.find(b"\x00")
else:
def truncate_zero(src):
"""
- 0x00以降を捨てる
+ drop after 0x00
"""
assert(type(src)==bytes)
pos = src.find(b"\x00")
if sys.version_info[0]<3:
def to_str(src):
+ """
+ str or unicode to str
+ """
t=type(src)
if t==unicode:
return src.encode('cp932')
raise "INVALID str: %s" % t
def from_str(src):
+ """
+ do nothing
+ """
return src
else:
def to_str(src):
+ """
+ bytes or str to str
+ """
t=type(src)
if t==str:
return src
raise "INVALID str: %s" % t
def from_str(src):
+ """
+ str to bytes
+ """
return src.encode('cp932')
+"""
+utility functions.
+"""
def radian_to_degree(x):
return x/math.pi * 180.0
-###############################################################################
-# geometry
-###############################################################################
+"""
+common structures.
+"""
class Vector2(object):
+ """
+ 2D coordinate for uv value
+ """
__slots__=['x', 'y']
def __init__(self, x=0, y=0):
self.x=x
class Vector3(object):
+ """
+ 3D coordinate for vertex position, normal direction
+ """
__slots__=['x', 'y', 'z']
def __init__(self, x=0, y=0, z=0):
self.x=x
class Quaternion(object):
+ """
+ rotation representation in vmd motion
+ """
__slots__=['x', 'y', 'z', 'w']
def __init__(self, x=0, y=0, z=0, w=1):
self.x=x
class RGBA(object):
+ """
+ material color
+ """
__slots__=['r', 'g', 'b', 'a']
def __init__(self, r=0, g=0, b=0, a=1):
self.r=r
else:
assert(False)
-
-
-
-###############################################################################
-# interface
-###############################################################################
-def load_pmd(path):
- size=os.path.getsize(path)
- f=open(path, "rb")
- l=PMDLoader()
- if l.load(path, f, size):
- return l
-
-def load_vmd(path):
- size=os.path.getsize(path)
- f=open(path, "rb")
- l=VMDLoader()
- if l.load(path, f, size):
- return l
-
-def load_vpd(path):
- f=open(path, 'rb')
- if not f:
- return;
- size=os.path.getsize(path)
- l=VPDLoader()
- if l.load(path, f, size):
- return l
-
-
-###############################################################################
-# debug
-###############################################################################
-def debug_pmd(path):
- l=load_pmd(path)
- if not l:
- print("fail to load")
- sys.exit()
-
- print(unicode(l).encode(ENCODING))
- print(l.comment.encode(ENCODING))
- print("<ボーン>".decode('utf-8').encode(ENCODING))
- for bone in l.no_parent_bones:
- print(bone.name.encode(ENCODING))
- bone.display()
- #for bone in l.bones:
- # uni="%s:%s" % (bone.english_name, bone.name)
- # print uni.encode(ENCODING)
- #for skin in l.morph_list:
- # uni="%s:%s" % (skin.english_name, skin.name)
- # print uni.encode(ENCODING)
- #for i, v in enumerate(l.vertices):
- # print i, v
- #for i, f in enumerate(l.indices):
- # print i, f
- for m in l.materials:
- print(m)
-
-def debug_pmd_write(path, out):
- l=load_pmd(path)
- if not l:
- print("fail to load")
- sys.exit()
-
- if not l.write(out):
- print("fail to write")
- sys.exit()
-
-def debug_vmd(path):
- l=load_vmd(path)
- if not l:
- print("fail to load")
- sys.exit()
- print(unicode(l).encode(ENCODING))
-
- #for m in l.motions[u'センター']:
- # print m.frame, m.pos
- for n, m in l.shapes.items():
- print(unicode(n).encode(ENCODING), getEnglishSkinName(n))
-
-def debug_vpd(path):
- l=load_vpd(path)
- if not l:
- print("fail to load")
- sys.exit()
- for bone in l.pose:
- print(unicode(bone).encode(ENCODING))
-
-if __name__=="__main__":
- if len(sys.argv)<2:
- print("usage: %s {pmd file}" % sys.argv[0])
- print("usage: %s {vmd file}" % sys.argv[0])
- print("usage: %s {vpd file}" % sys.argv[0])
- print("usage: %s {pmd file} {export pmdfile}" % sys.argv[0])
- sys.exit()
-
- path=sys.argv[1]
- if not os.path.exists(path):
- print("no such file: %s" % path)
-
- if path.lower().endswith('.pmd'):
- if len(sys.argv)==2:
- debug_pmd(path)
- else:
- debug_pmd_write(path, sys.argv[2])
- elif path.lower().endswith('.vmd'):
- debug_vmd(path)
- elif path.lower().endswith('.vpd'):
- debug_vpd(path)
- else:
- print("unknown file type: %s" % path)
- sys.exit()
-
# coding: utf-8
+"""
+PMDの読み込み
+http://blog.goo.ne.jp/torisu_tetosuki/e/209ad341d3ece2b1b4df24abf619d6e4
+"""
import os
import sys
import struct
from .mmd import *
-###############################################################################
-# PMD
-###############################################################################
-def UshortVector():
- return []
-
class Vertex(object):
+ """pmd vertex struct.
+
+ Attributes:
+ pos: Vector3
+ normal: Vector3
+ uv: Vector2
+ bone0: bone index
+ bone1: bone index
+ weight0: bone0 influence
+ edge_flag: int flag
+ """
__slots__=['pos', 'normal', 'uv', 'bone0', 'bone1', 'weight0', 'edge_flag']
def __init__(self, x=0, y=0, z=0, nx=0, ny=0, nz=0, u=0, v=0,
bone0=0, bone1=0, weight0=0, edge_flag=0):
self.edge_flag=edge_flag
def __str__(self):
- return "<%s %s %s, (%d, %d, %d)>" % (str(self.pos), str(self.normal), str(self.uv), self.bone0, self.bone1, self.weight0)
+ return "<%s %s %s, (%d, %d, %d)>" % (
+ str(self.pos),
+ str(self.normal),
+ str(self.uv),
+ self.bone0, self.bone1, self.weight0)
def __getitem__(self, key):
if key==0:
class Material(object):
+ """pmd material struct.
+
+ Attributes:
+ diffuse: RGBA
+ shinness: float
+ specular: RGB
+ ambient: RGB
+ vertex_count: indices length
+ _texture: texture file path
+ toon_index: int
+ flag: int
+ """
__slots__=[
'diffuse', 'shinness', 'specular',
'ambient', 'vertex_count', '_texture', 'toon_index', 'flag',
)
-# @return 各マテリアルについて、そのマテリアルが保持する面の回数だけ
-# マテリアル自身を返す
-def material_per_face(materials):
- for m in materials:
- for x in range(int(m.vertex_count/3)):
- yield m
-
-
class Bone(object):
+ """pmd material struct.
+
+ Attributes:
+ _name:
+ index:
+ type:
+ ik:
+ pos:
+ _english_name:
+ ik_index:
+ parent_index:
+ tail_index:
+
+ parent:
+ tail:
+ children:
+ """
# kinds
ROTATE = 0
ROTATE_MOVE = 1
'children', '_english_name', 'ik_index',
'parent_index', 'tail_index', 'tail',
]
- def getName(self): return from_str(self._name)
+ def getName(self):
+ """
+ return str(multibyte) in python2
+ return bytes in python3
+ """
+ return from_str(self._name)
def setName(self, name): self._name=to_str(name)
name=property(getName, setName)
def getEnglishName(self): return from_str(self._english_name)
class IO(object):
+ """pmd loader class.
+
+ Attributes:
+ io: internal use.
+ end: internal use.
+ pos: internal user.
+
+ version: pmd version number
+ _name: internal
+ """
__slots__=['io', 'end', 'pos',
'version', '_name', '_comment',
'_english_name', '_english_comment',