pmdとmqoの読み書きライブラリと、それを使ったblender2.57b向けaddonです。
+package方法
+===========
+$ python setup.py sdist
+
blender-2.57addonのインストール
===============================
アーカイブを解凍すると中にblender25-meshioというディレクトリができます。
次にblenderを起動して、(File)-(User Preferences)をオープン。
(Add-Ons)タブを選択。
+
+[Install Add-On...]をクリック
+{blender2.57bのインストールディレクトリ}/2.57/scripts/addons/pymeshio/__init__.pyを選択
+
Import-Exportの中から"meshio. (.pmd)(.mqo)"を探して右のチェックボックスを有効にします。これでaddonが有効になり、(File)メニューの(Import)と(Export)それぞれにpmdとmqoが現れます。
更新履歴
========
+20110918 1.9.0
+--------------
+blender2.59に対応(from . importがよろしくない)
+剛体修正
+
20110607 1.8.6
--------------
pmd exportの法線を修正。
20110523 1.8.4
--------------
-2.57bより新しくしてしまったのを修正。
+blender2.57bより新しくしてしまったのを修正。
20110523 1.8.3
--------------
bl_info = {
"name": "meshio. (.pmd)(.mqo)",
+ "version": (1, 9),
"author": "ousttrue",
- "blender": (2, 5, 7),
+ "blender": (2, 5, 9),
"api": 35622,
"location": "File > Import-Export",
"description": "Import-Export PMD/MQO meshes",
from io_utils import ImportHelper, ExportHelper
except:
from bpy_extras.io_utils import ImportHelper, ExportHelper
-from . import bl25 as bl
+import bl25 as bl
'''
filter_glob = StringProperty(default="*.pmd", options={'HIDDEN'})
def execute(self, context):
- from . import import_pmd
+ import import_pmd
bl.initialize('pmd_import', context.scene)
import_pmd._execute(**self.as_keywords(
ignore=("filter_glob",)))
use_selection = BoolProperty(name="Selection Only", description="Export selected objects only", default=False)
def execute(self, context):
- from . import export_pmd
+ import export_pmd
bl.initialize('pmd_export', context.scene)
export_pmd._execute(**self.as_keywords(
ignore=("check_existing", "filter_glob", "use_selection")))
soft_min=0.001, soft_max=100.0, default=0.1)
def execute(self, context):
- from . import import_mqo
+ import import_mqo
bl.initialize('mqo_import', context.scene)
import_mqo._execute(**self.as_keywords(
ignore=("filter_glob",)))
default=False)
def execute(self, context):
- from . import export_mqo
+ import export_mqo
export_mqo._execute(**self.as_keywords(
ignore=("check_existing", "filter_glob", "use_selection")))
return {'FINISHED'}
def isIKSolver(c):
return c.type=='IK'
+MMD_SHAPE_GROUP_NAME='_MMD_SHAPE'
+MMD_MB_NAME='mb_name'
+MMD_MB_COMMENT='mb_comment'
+MMD_COMMENT='comment'
+BASE_SHAPE_NAME='Basis'
+RIGID_NAME='rigid_name'
+RIGID_SHAPE_TYPE='rigid_shape_type'
+RIGID_PROCESS_TYPE='rigid_process_type'
+RIGID_BONE_NAME='rigid_bone_name'
+RIGID_GROUP='ribid_group'
+RIGID_INTERSECTION_GROUP='rigid_intersection_group'
+RIGID_WEIGHT='rigid_weight'
+RIGID_LINEAR_DAMPING='rigid_linear_damping'
+RIGID_ANGULAR_DAMPING='rigid_angular_damping'
+RIGID_RESTITUTION='rigid_restitution'
+RIGID_FRICTION='rigid_friction'
+CONSTRAINT_NAME='const_name'
+CONSTRAINT_A='const_a'
+CONSTRAINT_B='const_b'
+CONSTRAINT_POS_MIN='const_pos_min'
+CONSTRAINT_POS_MAX='const_pos_max'
+CONSTRAINT_ROT_MIN='const_rot_min'
+CONSTRAINT_ROT_MAX='const_rot_max'
+CONSTRAINT_SPRING_POS='const_spring_pos'
+CONSTRAINT_SPRING_ROT='const_spring_rot'
+TOON_TEXTURE_OBJECT='ToonTextures'
+
import bpy
# wrapper
-from . import bl25 as bl
+import bl25 as bl
def materialToMqo(m):
material=MQOMaterial(m.name, 3)
'tracker_url': 'http://sourceforge.jp/ticket/newticket.php?group_id=5081',
}
-MMD_SHAPE_GROUP_NAME='_MMD_SHAPE'
-MMD_MB_NAME='mb_name'
-MMD_MB_COMMENT='mb_comment'
-MMD_COMMENT='comment'
-BASE_SHAPE_NAME='Basis'
-RIGID_NAME='rigid_name'
-RIGID_SHAPE_TYPE='rigid_shape_type'
-RIGID_PROCESS_TYPE='rigid_process_type'
-RIGID_BONE_NAME='rigid_bone_name'
-#RIGID_LOCATION='rigid_loation'
-RIGID_GROUP='ribid_group'
-RIGID_INTERSECTION_GROUP='rigid_intersection_group'
-RIGID_WEIGHT='rigid_weight'
-RIGID_LINEAR_DAMPING='rigid_linear_damping'
-RIGID_ANGULAR_DAMPING='rigid_angular_damping'
-RIGID_RESTITUTION='rigid_restitution'
-RIGID_FRICTION='rigid_friction'
-CONSTRAINT_NAME='constraint_name'
-CONSTRAINT_A='const_a'
-CONSTRAINT_B='const_b'
-CONSTRAINT_POS_MIN='const_pos_min'
-CONSTRAINT_POS_MAX='const_pos_max'
-CONSTRAINT_ROT_MIN='const_rot_min'
-CONSTRAINT_ROT_MAX='const_rot_max'
-CONSTRAINT_SPRING_POS='const_spring_pos'
-CONSTRAINT_SPRING_ROT='const_spring_rot'
-TOON_TEXTURE_OBJECT='ToonTextures'
-
###############################################################################
# import
print('use meshio C module')
except ImportError:
# full python
- from .pymeshio import englishmap
- from .pymeshio import pmd
+ from pymeshio import englishmap
+ from pymeshio import pmd
# for 2.5
import mathutils
# wrapper
-from . import bl25 as bl
+import bl25 as bl
xrange=range
)
def __mesh(self, obj):
- if RIGID_SHAPE_TYPE in obj:
+ if bl.RIGID_SHAPE_TYPE in obj:
return
- if CONSTRAINT_A in obj:
+ if bl.CONSTRAINT_A in obj:
return
bl.message("export: %s" % obj.name)
baseMorph=None
# shape keys
- vg=bl.object.getVertexGroup(obj, MMD_SHAPE_GROUP_NAME)
+ vg=bl.object.getVertexGroup(obj, bl.MMD_SHAPE_GROUP_NAME)
# base
used=set()
for b in bl.object.getShapeKeys(obj):
- if b.name==BASE_SHAPE_NAME:
+ if b.name==bl.BASE_SHAPE_NAME:
baseMorph=self.__getOrCreateMorph('base', 0)
basis=b
# shape keys
for b in bl.object.getShapeKeys(obj):
- if b.name==BASE_SHAPE_NAME:
+ if b.name==bl.BASE_SHAPE_NAME:
continue
#print(b.name)
self.morphList.sort(key=getIndex)
def __rigidbody(self, obj):
- if not RIGID_SHAPE_TYPE in obj:
+ if not bl.RIGID_SHAPE_TYPE in obj:
return
self.rigidbodies.append(obj)
def __constraint(self, obj):
- if not CONSTRAINT_A in obj:
+ if not bl.CONSTRAINT_A in obj:
return
self.constraints.append(obj)
root=object_node_map[bl.object.getActive()]
o=root.o
self.englishName=o.name
- self.englishComment=o[MMD_COMMENT] if MMD_COMMENT in o else 'blender export\n'
- self.name=o[MMD_MB_NAME] if MMD_MB_NAME in o else 'Blenderエクスポート'
- self.comment=o[MMD_MB_COMMENT] if MMD_MB_COMMENT in o else 'Blnderエクスポート\n'
+ self.englishComment=o[bl.MMD_COMMENT] if bl.MMD_COMMENT in o else 'blender export\n'
+ self.name=o[bl.MMD_MB_NAME] if bl.MMD_MB_NAME in o else 'Blenderエクスポート'
+ self.comment=o[bl.MMD_MB_COMMENT] if bl.MMD_MB_COMMENT in o else 'Blnderエクスポート\n'
# ワンスキンメッシュを作る
self.oneSkinMesh=OneSkinMesh()
toonMeshObject=None
for o in bl.object.each():
try:
- if o.name.startswith(TOON_TEXTURE_OBJECT):
+ if o.name.startswith(bl.TOON_TEXTURE_OBJECT):
toonMeshObject=o
except:
p(o.name)
# rigid body
rigidNameMap={}
for i, obj in enumerate(self.oneSkinMesh.rigidbodies):
- name=obj[RIGID_NAME] if RIGID_NAME in obj else obj.name
- #print(name)
+ name=obj[bl.RIGID_NAME] if bl.RIGID_NAME in obj else obj.name
+ print(name)
rigidBody=pmd.RigidBody(name)
rigidNameMap[name]=i
- boneIndex=boneNameMap[obj[RIGID_BONE_NAME]]
+ boneIndex=boneNameMap[obj[bl.RIGID_BONE_NAME]]
if boneIndex==0:
boneIndex=0xFFFF
bone=self.skeleton.bones[0]
else:
bone=self.skeleton.bones[boneIndex]
rigidBody.boneIndex=boneIndex
- #rigidBody.position.x=obj[RIGID_LOCATION][0]
- #rigidBody.position.y=obj[RIGID_LOCATION][1]
- #rigidBody.position.z=obj[RIGID_LOCATION][2]
rigidBody.position.x=obj.location.x-bone.pos[0]
rigidBody.position.y=obj.location.z-bone.pos[2]
rigidBody.position.z=obj.location.y-bone.pos[1]
rigidBody.rotation.x=-obj.rotation_euler[0]
rigidBody.rotation.y=-obj.rotation_euler[2]
rigidBody.rotation.z=-obj.rotation_euler[1]
- rigidBody.processType=obj[RIGID_PROCESS_TYPE]
- rigidBody.group=obj[RIGID_GROUP]
- rigidBody.target=obj[RIGID_INTERSECTION_GROUP]
- rigidBody.weight=obj[RIGID_WEIGHT]
- rigidBody.linearDamping=obj[RIGID_LINEAR_DAMPING]
- rigidBody.angularDamping=obj[RIGID_ANGULAR_DAMPING]
- rigidBody.restitution=obj[RIGID_RESTITUTION]
- rigidBody.friction=obj[RIGID_FRICTION]
- if obj[RIGID_SHAPE_TYPE]==0:
+ rigidBody.processType=obj[bl.RIGID_PROCESS_TYPE]
+ rigidBody.group=obj[bl.RIGID_GROUP]
+ rigidBody.target=obj[bl.RIGID_INTERSECTION_GROUP]
+ rigidBody.weight=obj[bl.RIGID_WEIGHT]
+ rigidBody.linearDamping=obj[bl.RIGID_LINEAR_DAMPING]
+ rigidBody.angularDamping=obj[bl.RIGID_ANGULAR_DAMPING]
+ rigidBody.restitution=obj[bl.RIGID_RESTITUTION]
+ rigidBody.friction=obj[bl.RIGID_FRICTION]
+ if obj[bl.RIGID_SHAPE_TYPE]==0:
rigidBody.shapeType=pmd.SHAPE_SPHERE
rigidBody.w=obj.scale[0]
rigidBody.d=0
rigidBody.h=0
- elif obj[RIGID_SHAPE_TYPE]==1:
+ elif obj[bl.RIGID_SHAPE_TYPE]==1:
rigidBody.shapeType=pmd.SHAPE_BOX
rigidBody.w=obj.scale[0]
rigidBody.d=obj.scale[1]
rigidBody.h=obj.scale[2]
- elif obj[RIGID_SHAPE_TYPE]==2:
+ elif obj[bl.RIGID_SHAPE_TYPE]==2:
rigidBody.shapeType=pmd.SHAPE_CAPSULE
rigidBody.w=obj.scale[0]
rigidBody.h=obj.scale[2]
# constraint
for obj in self.oneSkinMesh.constraints:
- constraint=pmd.Constraint(obj[CONSTRAINT_NAME])
- constraint.rigidA=rigidNameMap[obj[CONSTRAINT_A]]
- constraint.rigidB=rigidNameMap[obj[CONSTRAINT_B]]
+ print(obj)
+ constraint=pmd.Constraint(obj[bl.CONSTRAINT_NAME])
+ constraint.rigidA=rigidNameMap[obj[bl.CONSTRAINT_A]]
+ constraint.rigidB=rigidNameMap[obj[bl.CONSTRAINT_B]]
constraint.pos.x=obj.location[0]
constraint.pos.y=obj.location[2]
constraint.pos.z=obj.location[1]
constraint.rot.x=-obj.rotation_euler[0]
constraint.rot.y=-obj.rotation_euler[2]
constraint.rot.z=-obj.rotation_euler[1]
- constraint.constraintPosMin.x=obj[CONSTRAINT_POS_MIN][0]
- constraint.constraintPosMin.y=obj[CONSTRAINT_POS_MIN][1]
- constraint.constraintPosMin.z=obj[CONSTRAINT_POS_MIN][2]
- constraint.constraintPosMax.x=obj[CONSTRAINT_POS_MAX][0]
- constraint.constraintPosMax.y=obj[CONSTRAINT_POS_MAX][1]
- constraint.constraintPosMax.z=obj[CONSTRAINT_POS_MAX][2]
- constraint.constraintRotMin.x=obj[CONSTRAINT_ROT_MIN][0]
- constraint.constraintRotMin.y=obj[CONSTRAINT_ROT_MIN][1]
- constraint.constraintRotMin.z=obj[CONSTRAINT_ROT_MIN][2]
- constraint.constraintRotMax.x=obj[CONSTRAINT_ROT_MAX][0]
- constraint.constraintRotMax.y=obj[CONSTRAINT_ROT_MAX][1]
- constraint.constraintRotMax.z=obj[CONSTRAINT_ROT_MAX][2]
- constraint.springPos.x=obj[CONSTRAINT_SPRING_POS][0]
- constraint.springPos.y=obj[CONSTRAINT_SPRING_POS][1]
- constraint.springPos.z=obj[CONSTRAINT_SPRING_POS][2]
- constraint.springRot.x=obj[CONSTRAINT_SPRING_ROT][0]
- constraint.springRot.y=obj[CONSTRAINT_SPRING_ROT][1]
- constraint.springRot.z=obj[CONSTRAINT_SPRING_ROT][2]
+ constraint.constraintPosMin.x=obj[bl.CONSTRAINT_POS_MIN][0]
+ constraint.constraintPosMin.y=obj[bl.CONSTRAINT_POS_MIN][1]
+ constraint.constraintPosMin.z=obj[bl.CONSTRAINT_POS_MIN][2]
+ constraint.constraintPosMax.x=obj[bl.CONSTRAINT_POS_MAX][0]
+ constraint.constraintPosMax.y=obj[bl.CONSTRAINT_POS_MAX][1]
+ constraint.constraintPosMax.z=obj[bl.CONSTRAINT_POS_MAX][2]
+ constraint.constraintRotMin.x=obj[bl.CONSTRAINT_ROT_MIN][0]
+ constraint.constraintRotMin.y=obj[bl.CONSTRAINT_ROT_MIN][1]
+ constraint.constraintRotMin.z=obj[bl.CONSTRAINT_ROT_MIN][2]
+ constraint.constraintRotMax.x=obj[bl.CONSTRAINT_ROT_MAX][0]
+ constraint.constraintRotMax.y=obj[bl.CONSTRAINT_ROT_MAX][1]
+ constraint.constraintRotMax.z=obj[bl.CONSTRAINT_ROT_MAX][2]
+ constraint.springPos.x=obj[bl.CONSTRAINT_SPRING_POS][0]
+ constraint.springPos.y=obj[bl.CONSTRAINT_SPRING_POS][1]
+ constraint.springPos.z=obj[bl.CONSTRAINT_SPRING_POS][2]
+ constraint.springRot.x=obj[bl.CONSTRAINT_SPRING_ROT][0]
+ constraint.springRot.y=obj[bl.CONSTRAINT_SPRING_ROT][1]
+ constraint.springRot.z=obj[bl.CONSTRAINT_SPRING_ROT][2]
io.constraints.append(constraint)
# 書き込み
print('use meshio C module')\r
except ImportError:\r
# full python\r
- from .pymeshio import mqo\r
+ from pymeshio import mqo\r
\r
# for 2.5\r
import bpy\r
\r
# wrapper\r
-from . import bl25 as bl\r
+import bl25 as bl\r
\r
def createMqoMaterial(m):\r
material = bpy.data.materials.new(m.getName())\r
'tracker_url': 'http://sourceforge.jp/ticket/newticket.php?group_id=5081',
}
-MMD_SHAPE_GROUP_NAME='_MMD_SHAPE'
-MMD_MB_NAME='mb_name'
-MMD_MB_COMMENT='mb_comment'
-MMD_COMMENT='comment'
-BASE_SHAPE_NAME='Basis'
-RIGID_NAME='rigid_name'
-RIGID_SHAPE_TYPE='rigid_shape_type'
-RIGID_PROCESS_TYPE='rigid_process_type'
-RIGID_BONE_NAME='rigid_bone_name'
-#RIGID_LOCATION='rigid_loation'
-RIGID_GROUP='ribid_group'
-RIGID_INTERSECTION_GROUP='rigid_intersection_group'
-RIGID_WEIGHT='rigid_weight'
-RIGID_LINEAR_DAMPING='rigid_linear_damping'
-RIGID_ANGULAR_DAMPING='rigid_angular_damping'
-RIGID_RESTITUTION='rigid_restitution'
-RIGID_FRICTION='rigid_friction'
-CONSTRAINT_NAME='const_name'
-CONSTRAINT_A='const_a'
-CONSTRAINT_B='const_b'
-CONSTRAINT_POS_MIN='const_pos_min'
-CONSTRAINT_POS_MAX='const_pos_max'
-CONSTRAINT_ROT_MIN='const_rot_min'
-CONSTRAINT_ROT_MAX='const_rot_max'
-CONSTRAINT_SPRING_POS='const_spring_pos'
-CONSTRAINT_SPRING_ROT='const_spring_rot'
-TOON_TEXTURE_OBJECT='ToonTextures'
-
###############################################################################
# import
print('use meshio C module')
except ImportError:
# full python
- from .pymeshio import englishmap
+ from pymeshio import englishmap
#from .pymeshio import mmd as pmd
#pmd.IO=pmd.PMDLoader
- from .pymeshio import pmd
+ from pymeshio import pmd
# for 2.5
import bpy
import mathutils
# wrapper
-from . import bl25 as bl
+import bl25 as bl
xrange=range
def __importToonTextures(io, tex_dir):
- mesh, meshObject=bl.mesh.create(TOON_TEXTURE_OBJECT)
- material=bl.material.create(TOON_TEXTURE_OBJECT)
+ mesh, meshObject=bl.mesh.create(bl.TOON_TEXTURE_OBJECT)
+ material=bl.material.create(bl.TOON_TEXTURE_OBJECT)
bl.mesh.addMaterial(mesh, material)
for toon in (io.toon_textures._toon_textures[i] for i in range(10)):
path=os.path.join(tex_dir, toon)
base=s
# create vertex group
- bl.object.addVertexGroup(obj, MMD_SHAPE_GROUP_NAME)
+ bl.object.addVertexGroup(obj, bl.MMD_SHAPE_GROUP_NAME)
hasShape=False
for i in s.indices:
if i in vertex_map:
hasShape=True
bl.object.assignVertexGroup(
- obj, MMD_SHAPE_GROUP_NAME, vertex_map[i], 0)
+ obj, bl.MMD_SHAPE_GROUP_NAME, vertex_map[i], 0)
if not hasShape:
return
assert(base)
# create base key
- baseShapeBlock=bl.object.addShapeKey(obj, BASE_SHAPE_NAME)
+ baseShapeBlock=bl.object.addShapeKey(obj, bl.BASE_SHAPE_NAME)
# mesh
mesh=bl.object.getData(obj)
mesh.update()
rot=c.rot
meshObject.rotation_euler=(-rot.x, -rot.z, -rot.y)
- meshObject[CONSTRAINT_NAME]=c._name
- meshObject[CONSTRAINT_A]=io.rigidbodies[c.rigidA]._name
- meshObject[CONSTRAINT_B]=io.rigidbodies[c.rigidB]._name
- meshObject[CONSTRAINT_POS_MIN]=VtoV(c.constraintPosMin)
- meshObject[CONSTRAINT_POS_MAX]=VtoV(c.constraintPosMax)
- meshObject[CONSTRAINT_ROT_MIN]=VtoV(c.constraintRotMin)
- meshObject[CONSTRAINT_ROT_MAX]=VtoV(c.constraintRotMax)
- meshObject[CONSTRAINT_SPRING_POS]=VtoV(c.springPos)
- meshObject[CONSTRAINT_SPRING_ROT]=VtoV(c.springRot)
+ meshObject[bl.CONSTRAINT_NAME]=c._name
+ meshObject[bl.CONSTRAINT_A]=io.rigidbodies[c.rigidA]._name
+ meshObject[bl.CONSTRAINT_B]=io.rigidbodies[c.rigidB]._name
+ meshObject[bl.CONSTRAINT_POS_MIN]=VtoV(c.constraintPosMin)
+ meshObject[bl.CONSTRAINT_POS_MAX]=VtoV(c.constraintPosMax)
+ meshObject[bl.CONSTRAINT_ROT_MIN]=VtoV(c.constraintRotMin)
+ meshObject[bl.CONSTRAINT_ROT_MAX]=VtoV(c.constraintRotMax)
+ meshObject[bl.CONSTRAINT_SPRING_POS]=VtoV(c.springPos)
+ meshObject[bl.CONSTRAINT_SPRING_ROT]=VtoV(c.springRot)
for meshObject in reversed(constraintMeshes):
bl.object.makeParent(container, meshObject)
rigidMeshes.append(meshObject)
bl.mesh.addMaterial(mesh, material)
meshObject.name='r_%03d' % i
- meshObject[RIGID_NAME]=rigid._name
+ meshObject[bl.RIGID_NAME]=rigid._name
#meshObject.draw_transparent=True
#meshObject.draw_wire=True
meshObject.draw_type='WIRE'
meshObject.rotation_euler=(-rot.x, -rot.z, -rot.y)
# custom properties
- meshObject[RIGID_SHAPE_TYPE]=rigid.shapeType
- meshObject[RIGID_PROCESS_TYPE]=rigid.processType
+ meshObject[bl.RIGID_SHAPE_TYPE]=rigid.shapeType
+ meshObject[bl.RIGID_PROCESS_TYPE]=rigid.processType
bone_name = englishmap.getEnglishBoneName(bone._name)
if not bone_name:
bone_name=bone._name
- meshObject[RIGID_BONE_NAME]=bone_name
+ meshObject[bl.RIGID_BONE_NAME]=bone_name
- meshObject[RIGID_GROUP]=rigid.group
- meshObject[RIGID_INTERSECTION_GROUP]=rigid.target
- meshObject[RIGID_WEIGHT]=rigid.weight
- meshObject[RIGID_LINEAR_DAMPING]=rigid.linearDamping
- meshObject[RIGID_ANGULAR_DAMPING]=rigid.angularDamping
- meshObject[RIGID_RESTITUTION]=rigid.restitution
- meshObject[RIGID_FRICTION]=rigid.friction
+ meshObject[bl.RIGID_GROUP]=rigid.group
+ meshObject[bl.RIGID_INTERSECTION_GROUP]=rigid.target
+ meshObject[bl.RIGID_WEIGHT]=rigid.weight
+ meshObject[bl.RIGID_LINEAR_DAMPING]=rigid.linearDamping
+ meshObject[bl.RIGID_ANGULAR_DAMPING]=rigid.angularDamping
+ meshObject[bl.RIGID_RESTITUTION]=rigid.restitution
+ meshObject[bl.RIGID_FRICTION]=rigid.friction
for meshObject in reversed(rigidMeshes):
bl.object.makeParent(container, meshObject)
if len(model_name)==0:
model_name=io._name
root=bl.object.createEmpty(model_name)
- root[MMD_MB_NAME]=io._name
- root[MMD_MB_COMMENT]=io._comment
- root[MMD_COMMENT]=io._english_comment
+ root[bl.MMD_MB_NAME]=io._name
+ root[bl.MMD_MB_COMMENT]=io._comment
+ root[bl.MMD_COMMENT]=io._english_comment
# toon textures
tex_dir=os.path.dirname(filepath)
setup(
name='pymeshio',
- version='1.8.6',
+ version='1.9.0',
description='pure python 3d model io library',
keywords=[],
author='ousttrue',