+++ /dev/null
-# Makefile for Sphinx documentation
-#
-
-# You can set these variables from the command line.
-SPHINXOPTS =
-SPHINXBUILD = sphinx-build
-PAPER =
-BUILDDIR = build
-
-# Internal variables.
-PAPEROPT_a4 = -D latex_paper_size=a4
-PAPEROPT_letter = -D latex_paper_size=letter
-ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
-
-.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest
-
-help:
- @echo "Please use \`make <target>' where <target> is one of"
- @echo " html to make standalone HTML files"
- @echo " dirhtml to make HTML files named index.html in directories"
- @echo " singlehtml to make a single large HTML file"
- @echo " pickle to make pickle files"
- @echo " json to make JSON files"
- @echo " htmlhelp to make HTML files and a HTML help project"
- @echo " qthelp to make HTML files and a qthelp project"
- @echo " devhelp to make HTML files and a Devhelp project"
- @echo " epub to make an epub"
- @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
- @echo " latexpdf to make LaTeX files and run them through pdflatex"
- @echo " text to make text files"
- @echo " man to make manual pages"
- @echo " changes to make an overview of all changed/added/deprecated items"
- @echo " linkcheck to check all external links for integrity"
- @echo " doctest to run all doctests embedded in the documentation (if enabled)"
-
-clean:
- -rm -rf $(BUILDDIR)/*
-
-html:
- $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
- @echo
- @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
-
-dirhtml:
- $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
- @echo
- @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
-
-singlehtml:
- $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
- @echo
- @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
-
-pickle:
- $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
- @echo
- @echo "Build finished; now you can process the pickle files."
-
-json:
- $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
- @echo
- @echo "Build finished; now you can process the JSON files."
-
-htmlhelp:
- $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
- @echo
- @echo "Build finished; now you can run HTML Help Workshop with the" \
- ".hhp project file in $(BUILDDIR)/htmlhelp."
-
-qthelp:
- $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
- @echo
- @echo "Build finished; now you can run "qcollectiongenerator" with the" \
- ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
- @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/MeshIO.qhcp"
- @echo "To view the help file:"
- @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/MeshIO.qhc"
-
-devhelp:
- $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
- @echo
- @echo "Build finished."
- @echo "To view the help file:"
- @echo "# mkdir -p $$HOME/.local/share/devhelp/MeshIO"
- @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/MeshIO"
- @echo "# devhelp"
-
-epub:
- $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
- @echo
- @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
-
-latex:
- $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
- @echo
- @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
- @echo "Run \`make' in that directory to run these through (pdf)latex" \
- "(use \`make latexpdf' here to do that automatically)."
-
-latexpdf:
- $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
- @echo "Running LaTeX files through pdflatex..."
- make -C $(BUILDDIR)/latex all-pdf
- @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
-
-text:
- $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
- @echo
- @echo "Build finished. The text files are in $(BUILDDIR)/text."
-
-man:
- $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
- @echo
- @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
-
-changes:
- $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
- @echo
- @echo "The overview file is in $(BUILDDIR)/changes."
-
-linkcheck:
- $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
- @echo
- @echo "Link check complete; look for any errors in the above output " \
- "or in $(BUILDDIR)/linkcheck/output.txt."
-
-doctest:
- $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
- @echo "Testing of doctests in the sources finished, look at the " \
- "results in $(BUILDDIR)/doctest/output.txt."
+++ /dev/null
-@ECHO OFF
-
-REM Command file for Sphinx documentation
-
-if "%SPHINXBUILD%" == "" (
- set SPHINXBUILD=sphinx-build
-)
-set BUILDDIR=build
-set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% source
-if NOT "%PAPER%" == "" (
- set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
-)
-
-if "%1" == "" goto help
-
-if "%1" == "help" (
- :help
- echo.Please use `make ^<target^>` where ^<target^> is one of
- echo. html to make standalone HTML files
- echo. dirhtml to make HTML files named index.html in directories
- echo. singlehtml to make a single large HTML file
- echo. pickle to make pickle files
- echo. json to make JSON files
- echo. htmlhelp to make HTML files and a HTML help project
- echo. qthelp to make HTML files and a qthelp project
- echo. devhelp to make HTML files and a Devhelp project
- echo. epub to make an epub
- echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
- echo. text to make text files
- echo. man to make manual pages
- echo. changes to make an overview over all changed/added/deprecated items
- echo. linkcheck to check all external links for integrity
- echo. doctest to run all doctests embedded in the documentation if enabled
- goto end
-)
-
-if "%1" == "clean" (
- for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
- del /q /s %BUILDDIR%\*
- goto end
-)
-
-if "%1" == "html" (
- %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
- echo.
- echo.Build finished. The HTML pages are in %BUILDDIR%/html.
- goto end
-)
-
-if "%1" == "dirhtml" (
- %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
- echo.
- echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
- goto end
-)
-
-if "%1" == "singlehtml" (
- %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
- echo.
- echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
- goto end
-)
-
-if "%1" == "pickle" (
- %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
- echo.
- echo.Build finished; now you can process the pickle files.
- goto end
-)
-
-if "%1" == "json" (
- %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
- echo.
- echo.Build finished; now you can process the JSON files.
- goto end
-)
-
-if "%1" == "htmlhelp" (
- %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
- echo.
- echo.Build finished; now you can run HTML Help Workshop with the ^
-.hhp project file in %BUILDDIR%/htmlhelp.
- goto end
-)
-
-if "%1" == "qthelp" (
- %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
- echo.
- echo.Build finished; now you can run "qcollectiongenerator" with the ^
-.qhcp project file in %BUILDDIR%/qthelp, like this:
- echo.^> qcollectiongenerator %BUILDDIR%\qthelp\MeshIO.qhcp
- echo.To view the help file:
- echo.^> assistant -collectionFile %BUILDDIR%\qthelp\MeshIO.ghc
- goto end
-)
-
-if "%1" == "devhelp" (
- %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
- echo.
- echo.Build finished.
- goto end
-)
-
-if "%1" == "epub" (
- %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
- echo.
- echo.Build finished. The epub file is in %BUILDDIR%/epub.
- goto end
-)
-
-if "%1" == "latex" (
- %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
- echo.
- echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
- goto end
-)
-
-if "%1" == "text" (
- %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
- echo.
- echo.Build finished. The text files are in %BUILDDIR%/text.
- goto end
-)
-
-if "%1" == "man" (
- %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
- echo.
- echo.Build finished. The manual pages are in %BUILDDIR%/man.
- goto end
-)
-
-if "%1" == "changes" (
- %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
- echo.
- echo.The overview file is in %BUILDDIR%/changes.
- goto end
-)
-
-if "%1" == "linkcheck" (
- %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
- echo.
- echo.Link check complete; look for any errors in the above output ^
-or in %BUILDDIR%/linkcheck/output.txt.
- goto end
-)
-
-if "%1" == "doctest" (
- %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
- echo.
- echo.Testing of doctests in the sources finished, look at the ^
-results in %BUILDDIR%/doctest/output.txt.
- goto end
-)
-
-:end
+++ /dev/null
-.. highlight:: c++
-
-C++ライブラリ
-=====================
-
-これがメイン機能。
-
-使い方
-------
-
-::
-
- #include <meshio.h>
- #include <iostream>
-
-
- int main(int argc, char **argv)
- {
- using namespace meshio;
-
- if(argc<2){
- std::wcout << "usage: " << argv[0] << " {mqo file}" << std::endl;
- return -1;
- }
- mqo::IO io;
- if(!io.read(argv[1])){
- std::wcout << "fail to read " << argv[1] << std::endl;
- return -1;
- }
-
- for(std::vector<mqo::Material>::iterator it=io.materials.begin();
- it!=io.materials.end();
- ++it)
- {
- std::wcout << it->getName() << std::endl;
- }
-
- return 0;
- }
-
+++ /dev/null
-# -*- coding: utf-8 -*-
-#
-# MeshIO documentation build configuration file, created by
-# sphinx-quickstart on Wed Aug 11 22:41:07 2010.
-#
-# This file is execfile()d with the current directory set to its containing dir.
-#
-# Note that not all possible configuration values are present in this
-# autogenerated file.
-#
-# All configuration values have a default; values that are commented out
-# serve to show the default.
-
-import sys, os
-
-# If extensions (or modules to document with autodoc) are in another directory,
-# add these directories to sys.path here. If the directory is relative to the
-# documentation root, use os.path.abspath to make it absolute, like shown here.
-#sys.path.insert(0, os.path.abspath('.'))
-
-# -- General configuration -----------------------------------------------------
-
-# If your documentation needs a minimal Sphinx version, state it here.
-#needs_sphinx = '1.0'
-
-# Add any Sphinx extension module names here, as strings. They can be extensions
-# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
-extensions = []
-
-# Add any paths that contain templates here, relative to this directory.
-templates_path = ['_templates']
-
-# The suffix of source filenames.
-source_suffix = '.rst'
-
-# The encoding of source files.
-#source_encoding = 'utf-8-sig'
-
-# The master toctree document.
-master_doc = 'index'
-
-# General information about the project.
-project = u'MeshIO'
-copyright = u'2010, ousttrue'
-
-# The version info for the project you're documenting, acts as replacement for
-# |version| and |release|, also used in various other places throughout the
-# built documents.
-#
-# The short X.Y version.
-version = '1.0'
-# The full version, including alpha/beta/rc tags.
-release = '1.0'
-
-# The language for content autogenerated by Sphinx. Refer to documentation
-# for a list of supported languages.
-#language = None
-
-# There are two options for replacing |today|: either, you set today to some
-# non-false value, then it is used:
-#today = ''
-# Else, today_fmt is used as the format for a strftime call.
-#today_fmt = '%B %d, %Y'
-
-# List of patterns, relative to source directory, that match files and
-# directories to ignore when looking for source files.
-exclude_patterns = []
-
-# The reST default role (used for this markup: `text`) to use for all documents.
-#default_role = None
-
-# If true, '()' will be appended to :func: etc. cross-reference text.
-#add_function_parentheses = True
-
-# If true, the current module name will be prepended to all description
-# unit titles (such as .. function::).
-#add_module_names = True
-
-# If true, sectionauthor and moduleauthor directives will be shown in the
-# output. They are ignored by default.
-#show_authors = False
-
-# The name of the Pygments (syntax highlighting) style to use.
-pygments_style = 'sphinx'
-
-# A list of ignored prefixes for module index sorting.
-#modindex_common_prefix = []
-
-
-# -- Options for HTML output ---------------------------------------------------
-
-# The theme to use for HTML and HTML Help pages. See the documentation for
-# a list of builtin themes.
-html_theme = 'default'
-
-# Theme options are theme-specific and customize the look and feel of a theme
-# further. For a list of options available for each theme, see the
-# documentation.
-#html_theme_options = {}
-
-# Add any paths that contain custom themes here, relative to this directory.
-#html_theme_path = []
-
-# The name for this set of Sphinx documents. If None, it defaults to
-# "<project> v<release> documentation".
-#html_title = None
-
-# A shorter title for the navigation bar. Default is the same as html_title.
-#html_short_title = None
-
-# The name of an image file (relative to this directory) to place at the top
-# of the sidebar.
-#html_logo = None
-
-# The name of an image file (within the static path) to use as favicon of the
-# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
-# pixels large.
-#html_favicon = None
-
-# Add any paths that contain custom static files (such as style sheets) here,
-# relative to this directory. They are copied after the builtin static files,
-# so a file named "default.css" will overwrite the builtin "default.css".
-html_static_path = ['_static']
-
-# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
-# using the given strftime format.
-#html_last_updated_fmt = '%b %d, %Y'
-
-# If true, SmartyPants will be used to convert quotes and dashes to
-# typographically correct entities.
-#html_use_smartypants = True
-
-# Custom sidebar templates, maps document names to template names.
-#html_sidebars = {}
-
-# Additional templates that should be rendered to pages, maps page names to
-# template names.
-#html_additional_pages = {}
-
-# If false, no module index is generated.
-#html_domain_indices = True
-
-# If false, no index is generated.
-#html_use_index = True
-
-# If true, the index is split into individual pages for each letter.
-#html_split_index = False
-
-# If true, links to the reST sources are added to the pages.
-#html_show_sourcelink = True
-
-# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
-#html_show_sphinx = True
-
-# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
-#html_show_copyright = True
-
-# If true, an OpenSearch description file will be output, and all pages will
-# contain a <link> tag referring to it. The value of this option must be the
-# base URL from which the finished HTML is served.
-#html_use_opensearch = ''
-
-# This is the file name suffix for HTML files (e.g. ".xhtml").
-#html_file_suffix = None
-
-# Output file base name for HTML help builder.
-htmlhelp_basename = 'MeshIOdoc'
-
-
-# -- Options for LaTeX output --------------------------------------------------
-
-# The paper size ('letter' or 'a4').
-#latex_paper_size = 'letter'
-
-# The font size ('10pt', '11pt' or '12pt').
-#latex_font_size = '10pt'
-
-# Grouping the document tree into LaTeX files. List of tuples
-# (source start file, target name, title, author, documentclass [howto/manual]).
-latex_documents = [
- ('index', 'MeshIO.tex', u'MeshIO Documentation',
- u'ousttrue', 'manual'),
-]
-
-# The name of an image file (relative to this directory) to place at the top of
-# the title page.
-#latex_logo = None
-
-# For "manual" documents, if this is true, then toplevel headings are parts,
-# not chapters.
-#latex_use_parts = False
-
-# If true, show page references after internal links.
-#latex_show_pagerefs = False
-
-# If true, show URL addresses after external links.
-#latex_show_urls = False
-
-# Additional stuff for the LaTeX preamble.
-#latex_preamble = ''
-
-# Documents to append as an appendix to all manuals.
-#latex_appendices = []
-
-# If false, no module index is generated.
-#latex_domain_indices = True
-
-
-# -- Options for manual page output --------------------------------------------
-
-# One entry per manual page. List of tuples
-# (source start file, name, description, authors, manual section).
-man_pages = [
- ('index', 'meshio', u'MeshIO Documentation',
- [u'ousttrue'], 1)
-]
+++ /dev/null
-.. MeshIO documentation master file, created by
- sphinx-quickstart on Wed Aug 11 22:41:07 2010.
- You can adapt this file completely to your liking, but it should at least
- contain the root `toctree` directive.
-
-##########
-MeshIO
-##########
-
-ポリゴンメッシュ読み込みライブラリ。
-
-**************
-Python Binding
-**************
-Blender用のmqo, pmd importer/exporter を同梱。
-
-`Download <http://sourceforge.jp/projects/meshio/releases/>`_
-
-**********
-Source
-**********
-snapshotからソースアーカイブをダウンロードできます。
-
-http://git.sourceforge.jp/view?p=meshio/MeshIO.git;a=tree
-
-****
-機能
-****
-
-.. toctree::
- :maxdepth: 2
-
- c++
- python/index
-
-****
-作者
-****
-ツッコミはこちらへ
-
-http://d.hatena.ne.jp/ousttrue/
-
-******************
-Indices and tables
-******************
-
-* :ref:`genindex`
-* :ref:`modindex`
-* :ref:`search`
-
+++ /dev/null
-README.txt
-mqo.i
-pmd.i
-setup.py
-vmd.i
-./__init__.py
-./englishmap.py
-./mqo.py
-./pmd.py
-./vmd.py
+++ /dev/null
-build: setup.py mqo.i vmd.i pmd.i
- $(PYTHON) setup.py build
-
-rebuild: clean build
-
-install: build
- $(PYTHON) setup.py install
-
-bdist: build
- $(PYTHON) setup.py bdist
-
-bdist_egg: build
- $(PYTHON) setup.py bdist_egg
-
-sdist: build
- $(PYTHON) setup.py sdist
-
-windows: build
- $(PYTHON) setup.py bdist_wininst
-
-clean:
- rm -rf build dist
- touch *.i
-
+++ /dev/null
-# coding: cp932\r
-\r
-==============\r
-MeshIO library\r
-==============\r
-\82±\82Ì\83\89\83C\83u\83\89\83\8a\82Í\81Amqo\82Æpmd\82Ævmd\82Ì\93Ç\82Ý\8d\9e\82Ý\83\89\83C\83u\83\89\83\8a\82Å\82·\81B\r
-\r
+++ /dev/null
-all: copy
-
-copy: bl24.py bl25.py mqo_import.py mqo_export.py pmd_import.py pmd_export.py
- $(PYTHON2) cp.py $^
-
+++ /dev/null
-# coding: utf-8
-import sys
-import os
-
-try:
- import Blender
- from Blender import Mathutils
- import bpy
-except:
- pass
-
-# ファイルシステムの文字コード
-# 改造版との共用のため
-FS_ENCODING=sys.getfilesystemencoding()
-if os.path.exists(os.path.dirname(sys.argv[0])+"/utf8"):
- INTERNAL_ENCODING='utf-8'
-else:
- INTERNAL_ENCODING=FS_ENCODING
-
-def to_internal_encoding(fn):
- '''
- decorator for fix string encoding
- '''
- def newfn(*args):
- return fn(*[
- v.encode(INTERNAL_ENCODING) if isinstance(v, unicode) else v
- for v in args])
- return newfn
-
-def register():
- pass
-
-def unregister():
- pass
-
-SCENE=None
-def initialize(name, scene):
- global SCENE
- SCENE=scene
- progress_start(name)
- # set object mode
- mode_edit = Blender.Window.EditMode()
- if mode_edit:
- Blender.Window.EditMode(0)
-
-def finalize():
- scene.update(SCENE)
- progress_finish()
- # restore edit mode
- #if mode_edit:
- # Blender.Window.EditMode(1)
-
-@to_internal_encoding
-def message(msg):
- res=Blender.Draw.PupMenu(msg + "%t|OK")
- print(res)
-
-def enterEditMode():
- Blender.Window.EditMode(1)
-
-def enterObjectMode():
- Blender.Window.EditMode(0)
-
-def enterPoseMode():
- Blender.Window.PoseMode(1)
-
-def createVector(x, y, z):
- return Mathutils.Vector(x, y, z)
-
-
-class Writer(object):
- '''
- io wrapper
- '''
- __slots__=[
- 'io', 'encoding',
- ]
- def __init__(self, path, encoding):
- '''
- path: file path to open
- encoding: text encoding to write
-
- '''
- self.io=open(path, "wb")
- self.encoding=encoding
-
- def write(self, s):
- self.io.write(s)
-
- def flush(self):
- self.io.flush()
-
- def close(self):
- self.io.close()
-
-
-class ProgressBar(object):
- '''
- progress bar wrapper
- '''
- __slots__=['base', 'start', 'progress',]
- def __init__(self, base):
- print("#### %s ####" % base)
- self.base=base
- self.start=Blender.sys.time()
- self.set('<start>', 0)
- Blender.Window.WaitCursor(1)
-
- def advance(self, message, progress):
- self.progress+=float(progress)
- self._print(message)
-
- def set(self, message, progress):
- self.progress=float(progress)
- self._print(message)
-
- @to_internal_encoding
- def _print(self, message):
- print(message.decode(INTERNAL_ENCODING))
- message="%s: %s" % (self.base, message)
- Blender.Window.DrawProgressBar(self.progress, message)
-
- def finish(self):
- self.progress=1.0
- message='finished in %.2f sec' % (Blender.sys.time()-self.start)
- self.set(message, 1.0)
- Blender.Window.WaitCursor(0)
- Blender.Redraw()
-
-def progress_start(base):
- global progressBar
- progressBar=ProgressBar(base)
-
-def progress_finish():
- global progressBar
- progressBar.finish()
-
-def progress_print(message, progress=0.05):
- global progressBar
- progressBar.advance(message, progress)
-
-def progress_set(message, progress):
- global progressBar
- progressBar.set(message, progress)
-
-
-class scene:
- @staticmethod
- def update(scene):
- scene.update(0)
-
-
-class object:
- @staticmethod
- @to_internal_encoding
- def createEmpty(name):
- global SCENE
- empty=SCENE.objects.new("Empty")
- empty.setName(name)
- return empty
-
- @staticmethod
- def each():
- for o in SCENE.objects:
- yield o
-
- @staticmethod
- def makeParent(parent, child):
- parent.makeParent([child])
-
- @staticmethod
- def duplicate(o):
- new_mesh, new_object=mesh.create(o.name.decode(INTERNAL_ENCODING))
- # not apply modifiers
- new_mesh.getFromObject(o.name, 1)
- # apply matrix
- #o.setMatrix(o.matrixWorld)
- return new_mesh, new_object
-
- @staticmethod
- def delete(o):
- global SCENE
- SCENE.objects.unlink(o)
-
- @staticmethod
- def getData(o):
- return o.getData(mesh=True)
-
- @staticmethod
- def select(o):
- o.select(True)
-
- @staticmethod
- def activate(o):
- global SCENE
- o.select(True )
- SCENE.objects.active=o
-
- @staticmethod
- def getActive():
- global SCENE
- return SCENE.objects.active
-
- @staticmethod
- def deselectAll():
- for o in bpy.data.scenes.active.objects:
- o.select(False)
-
- @staticmethod
- def setLayerMask(o, layers):
- mask=0
- for i, enable in enumerate(layers):
- if enable!=0:
- mask+=(1<<i)
- o.Layers=mask
-
- @staticmethod
- def isVisible(o):
- return o.restrictDisplay
-
- @staticmethod
- def getShapeKeys(o):
- return o.getData(mesh=True).key.blocks
-
- @staticmethod
- @to_internal_encoding
- def addShapeKey(o, name):
- mesh=o.getData(mesh=True)
- mesh.insertKey()
- block=mesh.key.blocks[-1]
- block.name=name
- return block
-
- @staticmethod
- def hasShapeKey(o):
- return o.getData(mesh=True).key
-
- @staticmethod
- def pinShape(o, enable):
- o.pinShape=enable
-
- @staticmethod
- def setActivateShapeKey(o, index):
- o.activeShape=index
-
- @staticmethod
- def getPose(o):
- return o.getPose()
-
- @staticmethod
- @to_internal_encoding
- def addVertexGroup(o, name):
- o.getData(mesh=True).addVertGroup(name)
-
- @staticmethod
- @to_internal_encoding
- def assignVertexGroup(o, name, index, weight):
- o.getData(mesh=True).assignVertsToGroup(name,
- [index], weight, Blender.Mesh.AssignModes.ADD)
-
- @staticmethod
- def getVertexGroupNames(o):
- return o.getData(mesh=True).getVertGroupNames()
-
- @staticmethod
- @to_internal_encoding
- def getVertexGroup(o, name):
- indices=[]
- for index in o.getData(mesh=True).getVertsFromGroup(name):
- indices.append(index)
- return indices
-
- @staticmethod
- def createBoneGroup(o, name, color_set='DEFAULT'):
- # create group
- object.activate(o)
- enterPoseMode()
- bpy.ops.pose.group_add()
- # set name
- pose=object.getPose(o)
- g=pose.active_bone_group
- g.name=name
- g.color_set=color_set
-
- @staticmethod
- def boneGroups(o):
- return object.getPose(o).bone_groups
-
-
-class modifier:
- @staticmethod
- def addMirror(mesh_object):
- return mesh_object.modifiers.append(Blender.Modifier.Types.MIRROR)
-
- @staticmethod
- def addArmature(mesh_object, armature_object):
- mod=mesh_object.modifiers.append(Blender.Modifier.Types.ARMATURE)
- mod[Blender.Modifier.Settings.OBJECT] = armature_object
- mod[Blender.Modifier.Settings.ENVELOPES] = False
-
- @staticmethod
- def hasType(mesh_object, type_name):
- for mod in mesh_object.modifiers:
- if mod.name.upper()==type_name.upper():
- return True
-
- @staticmethod
- def isType(m, type_name):
- return m.name.upper()==type_name.upper()
-
- @staticmethod
- def getArmatureObject(m):
- return m[Blender.Modifier.Settings.OBJECT]
-
-
-class shapekey:
- @staticmethod
- def assign(b, index, pos):
- b.data[index]=pos
-
- @staticmethod
- def getByIndex(b, index):
- return b.data[index]
-
- @staticmethod
- def get(b):
- return b.data
-
-
-class texture:
- @staticmethod
- @to_internal_encoding
- def create(path):
- try:
- image = Blender.Image.Load(path)
- except IOError:
- image = None
- texture = Blender.Texture.New(path)
- texture.type = Blender.Texture.Types.IMAGE
- texture.image = image
- texture.imageFlags|=Blender.Texture.ImageFlags.USEALPHA
- return texture, image
-
- @staticmethod
- def getPath(t):
- image=t.getImage()
- if image:
- return image.getFilename()
-
-
-class material:
- @staticmethod
- @to_internal_encoding
- def create(name):
- m = Blender.Material.New(name)
- return m
-
- @staticmethod
- def get(material_name):
- return Blender.Material.Get(material_name)
-
- @staticmethod
- def addTexture(m, texture, enable=True):
- for i in xrange(10):
- if m.textures[i]:
- continue
- if enable:
- m.mode = m.mode | Blender.Material.Modes.TEXFACE
- m.setTexture(i, texture, Blender.Texture.TexCo.UV)
- else:
- m.setTexture(i, texture)
- material.setUseTexture(m, i, False)
- return i
-
- @staticmethod
- def getTexture(m, index):
- return m.textures[index].tex
-
- @staticmethod
- def hasTexture(m):
- return len(m.getTextures())>0
-
- @staticmethod
- def setUseTexture(m, index, enable):
- enabledTextures=set(m.enabledTextures)
- if enable:
- enabledTextures.add(index)
- else:
- enabledTextures.remove(index)
- m.enabledTextures=list(enabledTextures)
-
- @staticmethod
- def eachTexturePath(m, dirname):
- for texture in m.getTextures():
- if texture and texture.tex and texture.tex.getImage():
- image=texture.tex.getImage()
- if not image:
- continue
- yield image.getFilename()
-
- @staticmethod
- def eachEnalbeTexturePath(m, dirname):
- for i, texture in enumerate(m.getTextures()):
- if (i in m.enabledTextures) and texture and texture.tex and texture.tex.getImage():
- image=texture.tex.getImage()
- if not image:
- continue
- yield image.getFilename()
-
-
-class mesh:
- @staticmethod
- @to_internal_encoding
- def create(name):
- global SCENE
- m=Blender.Mesh.New()
- o=SCENE.objects.new(m, name)
- return m, o
-
- @staticmethod
- def addGeometry(m, vertices, faces):
- m.verts.extend(vertices)
- new_faces=m.faces.extend(faces,
- #ignoreDups=True,
- indexList=True)
- m.update()
-
- @staticmethod
- def hasUV(m):
- return m.faceUV
-
- @staticmethod
- def useVertexUV(m):
- m.vertexUV = 1
-
- @staticmethod
- def addUV(m):
- m.addUVLayer('NewUV')
-
- @staticmethod
- def hasFaceUV(m, i, face):
- return len(face.uv)>0
-
- @staticmethod
- def getFaceUV(m, i, face, count=3):
- return face.uv
-
- @staticmethod
- def setFaceUV(m, i, face, uv_array, image):
- face.uv=[Mathutils.Vector(uv[0], uv[1]) for uv in uv_array]
- if image:
- face.image=image
-
- @staticmethod
- def vertsDelete(m, remove_vertices):
- m.verts.delete(remove_vertices)
-
- @staticmethod
- def setSmooth(m, smoothing):
- m.mode |= Blender.Mesh.Modes.AUTOSMOOTH
- m.degr=int(smoothing)
- #m.smooth()
-
- @staticmethod
- def recalcNormals(mesh_object):
- m=mesh_object.getData(mesh=True)
- m.calcNormals()
-
- @staticmethod
- def flipNormals(m):
- m.flipNormals()
-
- @staticmethod
- def addMaterial(m, material):
- m.materials+=[material]
-
- @staticmethod
- def getMaterial(m, index):
- return m.materials[index]
-
-
-class vertex:
- @staticmethod
- def getNormal(v):
- return v.no
-
- @staticmethod
- def setNormal(v, normal):
- v.no=Mathutils.Vector(*normal)
-
- @staticmethod
- def setUv(v, uv):
- v.uvco=uv
-
-
-class face:
- @staticmethod
- def getVertexCount(face):
- return len(face.v)
-
- @staticmethod
- def getVertices(face):
- return [v.index for v in face.v]
-
- @staticmethod
- def getIndices(face):
- return [face.verts[0].index, face.verts[1].index, face.verts[2].index]
-
- @staticmethod
- def setMaterial(face, material_index):
- face.mat=material_index
-
- @staticmethod
- def getMaterialIndex(face):
- return face.mat
-
- @staticmethod
- def setNormal(face, normal):
- face.no=normal
-
- @staticmethod
- def getNormal(face):
- return face.no
-
- @staticmethod
- def setSmooth(face, isSmooth):
- face.smooth=1 if isSmooth else 0
-
-
-class armature:
- @staticmethod
- def create():
- global SCENE
- armature = Blender.Armature.New()
- armature_object = SCENE.objects.new(armature)
-
- # set XRAY
- armature_object.drawMode = (
- armature_object.drawMode | Blender.Object.DrawModes.XRAY)
- # armature settings
- armature.drawType = Blender.Armature.OCTAHEDRON
- armature.drawNames=True
- armature.envelopes = False
- armature.vertexGroups = True
- armature.mirrorEdit = True
-
- return armature, armature_object
-
- @staticmethod
- def makeEditable(armature_object):
- # create armature
- armature_object.getData().makeEditable()
-
- @staticmethod
- def createIkConstraint(armature_object, p_bone, effector_name, ik):
- cSetting = Blender.Constraint.Settings
- # IK solver
- constraint = p_bone.constraints.append(Blender.Constraint.Type.IKSOLVER)
- constraint[cSetting.CHAINLEN]=len(ik.children)
- constraint[cSetting.TARGET]=armature_object
- constraint[cSetting.USETIP]=False
- constraint[cSetting.BONE]=effector_name
- # not used. place folder when export.
- constraint[cSetting.ROTWEIGHT]=ik.weight
- constraint[cSetting.ITERATIONS]=ik.iterations * 10
- return constraint
-
- @staticmethod
- @to_internal_encoding
- def createBone(armature_object, name):
- bone=Blender.Armature.Editbone()
- bone.name=name
- armature_object.bones[name]=bone
- return bone
-
- @staticmethod
- def update(armature):
- armature.update()
-
-
-class bone:
- @staticmethod
- def setConnected(bone):
- bone.options+=[Blender.Armature.CONNECTED]
-
- @staticmethod
- def isConnected(b):
- return Blender.Armature.CONNECTED in b.options
-
- @staticmethod
- def setLayerMask(bone, layers):
- mask=0
- for i, enable in enumerate(layers):
- if enable!=0:
- mask+=(1<<i)
- bone.layerMask=mask
-
- @staticmethod
- def getHeadLocal(b):
- return b.head['ARMATURESPACE'][0:3]
-
- @staticmethod
- def getTailLocal(b):
- return b.tail['ARMATURESPACE'][0:3]
-
-
-class constraint:
- @staticmethod
- def ikChainLen(c):
- return c[Blender.Constraint.Settings.CHAINLEN]
-
- @staticmethod
- def ikTarget(c):
- return c[Blender.Constraint.Settings.BONE]
-
- @staticmethod
- def ikItration(c):
- return c[Blender.Constraint.Settings.ITERATIONS]
-
- @staticmethod
- def ikRotationWeight(c):
- return c[Blender.Constraint.Settings.ROTWEIGHT]
-
- @staticmethod
- def isIKSolver(c):
- return c.type==Blender.Constraint.Type.IKSOLVER
-
+++ /dev/null
-# coding: utf-8
-import os
-import sys
-import time
-import functools
-
-try:
- import bpy
- import mathutils
-except:
- pass
-
-FS_ENCODING=sys.getfilesystemencoding()
-if os.path.exists(os.path.dirname(sys.argv[0])+"/utf8"):
- INTERNAL_ENCODING='utf-8'
-else:
- INTERNAL_ENCODING=FS_ENCODING
-
-def register():
- pass
-
-def unregister():
- pass
-
-SCENE=None
-def initialize(name, scene):
- global SCENE
- SCENE=scene
- progress_start(name)
-
-def finalize():
- scene.update(SCENE)
- progress_finish()
-
-def message(msg):
- print(msg)
-
-def enterEditMode():
- bpy.ops.object.mode_set(mode='EDIT', toggle=False)
-
-def enterObjectMode():
- bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
-
-def enterPoseMode():
- bpy.ops.object.mode_set(mode='POSE', toggle=False)
-
-def createVector(x, y, z):
- return mathutils.Vector([x, y, z])
-
-
-class Writer(object):
- '''
- io wrapper
- '''
- def __init__(self, path, encoding):
- self.io=open(path, "wb")
- self.encoding=encoding
-
- def write(self, s):
- self.io.write(s.encode(self.encoding))
-
- def flush(self):
- self.io.flush()
-
- def close(self):
- self.io.close()
-
-
-class ProgressBar(object):
- '''
- progress bar wrapper
- '''
- def __init__(self, base):
- print("#### %s ####" % base)
- self.base=base
- self.start=time.time()
- self.set('<start>', 0)
-
- def advance(self, message, progress):
- self.progress+=float(progress)
- self._print(message)
-
- def set(self, message, progress):
- self.progress=float(progress)
- self._print(message)
-
- def _print(self, message):
- print(message)
- message="%s: %s" % (self.base, message)
- #Blender.Window.DrawProgressBar(self.progress, message)
-
- def finish(self):
- self.progress=1.0
- message='finished in %.2f sec' % (time.time()-self.start)
- self.set(message, 1.0)
-
-def progress_start(base):
- global progressBar
- progressBar=ProgressBar(base)
-
-def progress_finish():
- global progressBar
- progressBar.finish()
-
-def progress_print(message, progress=0.05):
- global progressBar
- progressBar.advance(message, progress)
-
-def progress_set(message, progress):
- global progressBar
- progressBar.set(message, progress)
-
-
-class scene:
- @staticmethod
- def update(scene):
- scene.update()
-
-
-class object:
- @staticmethod
- def createEmpty(name):
- global SCENE
- empty=bpy.data.objects.new(name, None)
- SCENE.objects.link(empty)
- return empty
-
- @staticmethod
- def each():
- for o in SCENE.objects:
- yield o
-
- @staticmethod
- def makeParent(parent, child):
- child.parent=parent
-
- @staticmethod
- def duplicate(o):
- global SCENE
- bpy.ops.object.select_all(action='DESELECT')
- o.select=True
- SCENE.objects.active=o
- bpy.ops.object.duplicate()
- dumy=SCENE.objects.active
- #bpy.ops.object.rotation_apply()
- #bpy.ops.object.scale_apply()
- #bpy.ops.object.location_apply()
- return dumy.data, dumy
-
- @staticmethod
- def delete(o):
- global SCENE
- SCENE.objects.unlink(o)
-
- @staticmethod
- def getData(o):
- return o.data
-
- @staticmethod
- def select(o):
- o.select=True
-
- @staticmethod
- def activate(o):
- global SCENE
- o.select=True
- SCENE.objects.active=o
-
- @staticmethod
- def getActive():
- global SCENE
- return SCENE.objects.active
-
- @staticmethod
- def deselectAll():
- bpy.ops.object.select_all(action='DESELECT')
-
- @staticmethod
- def setLayerMask(object, layers):
- layer=[]
- for i in range(20):
- try:
- layer.append(True if layers[i]!=0 else False)
- except IndexError:
- layer.append(False)
- object.layers=layer
-
- @staticmethod
- def isVisible(o):
- return False if o.hide else True
-
- @staticmethod
- def getShapeKeys(o):
- return o.data.shape_keys.keys
-
- @staticmethod
- def addShapeKey(o, name):
- try:
- return o.shape_key_add(name)
- except:
- return o.add_shape_key(name)
-
- @staticmethod
- def hasShapeKey(o):
- return o.data.shape_keys
-
- @staticmethod
- def pinShape(o, enable):
- o.show_only_shape_key=enable
-
- @staticmethod
- def setActivateShapeKey(o, index):
- o.active_shape_key_index=index
-
- @staticmethod
- def getPose(o):
- return o.pose
-
- @staticmethod
- def getVertexGroup(o, name):
- indices=[]
- for i, v in enumerate(o.data.vertices):
- for g in v.groups:
- if o.vertex_groups[g.group].name==name:
- indices.append(i)
- return indices
-
- @staticmethod
- def getVertexGroupNames(o):
- for g in o.vertex_groups:
- yield g.name
-
- @staticmethod
- def addVertexGroup(o, name):
- o.vertex_groups.new(name)
-
- @staticmethod
- def assignVertexGroup(o, name, index, weight):
- g=o.vertex_groups[name]
- o.vertex_groups.assign([index], g, weight, 'ADD')
-
- @staticmethod
- def createBoneGroup(o, name, color_set='DEFAULT'):
- # create group
- object.activate(o)
- enterPoseMode()
- bpy.ops.pose.group_add()
- # set name
- pose=object.getPose(o)
- g=pose.bone_groups.active
- g.name=name
- g.color_set=color_set
-
- @staticmethod
- def boneGroups(o):
- return object.getPose(o).bone_groups
-
-
-class modifier:
- @staticmethod
- def addMirror(mesh_object):
- return mesh_object.modifiers.new("Modifier", "MIRROR")
-
- @staticmethod
- def addArmature(mesh_object, armature_object):
- mod=mesh_object.modifiers.new("Modifier", "ARMATURE")
- mod.object = armature_object
- mod.use_bone_envelopes=False
-
- @staticmethod
- def hasType(mesh_object, type_name):
- for mod in mesh_object.modifiers:
- if mod.type==type_name.upper():
- return True
-
- @staticmethod
- def isType(m, type_name):
- return m.type==type_name.upper()
-
- @staticmethod
- def getArmatureObject(m):
- return m.object
-
-
-class shapekey:
- @staticmethod
- def assign(shapeKey, index, pos):
- shapeKey.data[index].co=pos
-
- @staticmethod
- def getByIndex(b, index):
- return b.data[index].co
-
- @staticmethod
- def get(b):
- for k in b.data:
- yield k.co
-
-
-class texture:
- @staticmethod
- def create(path):
- texture=bpy.data.textures.new(os.path.basename(path), 'IMAGE')
- texture.use_mipmap=True
- texture.use_interpolation=True
- texture.use_alpha=True
- try:
- image=bpy.data.images.load(path)
- except SystemError:
- image=bpy.data.images.new('Image')
- texture.image=image
- return texture, image
-
- @staticmethod
- def getPath(t):
- if t.type=="IMAGE":
- image=t.image
- if image:
- return image.filepath
-
-
-class material:
- @staticmethod
- def create(name):
- return bpy.data.materials.new(name)
-
- @staticmethod
- def get(material_name):
- return bpy.data.materials[material_name]
-
- @staticmethod
- def addTexture(material, texture, enable=True):
- # search free slot
- index=None
- for i, slot in enumerate(material.texture_slots):
- if not slot:
- index=i
- break
- if index==None:
- return
- #
- #material.add_texture(texture, "UV", "COLOR")
- #slot=material.texture_slots.add()
- slot=material.texture_slots.create(index)
- slot.texture=texture
- slot.texture_coords='UV'
- slot.blend_type='MULTIPLY'
- slot.use_map_alpha=True
- slot.use=enable
- return index
-
- @staticmethod
- def getTexture(m, index):
- return m.texture_slots[index].texture
-
- @staticmethod
- def hasTexture(m):
- return m.texture_slots[0]
-
- @staticmethod
- def setUseTexture(m, index, enable):
- m.use_textures[index]=enable
-
- @staticmethod
- def eachTexturePath(m):
- for slot in m.texture_slots:
- if slot and slot.texture:
- texture=slot.texture
- if texture.type=="IMAGE":
- image=texture.image
- if not image:
- continue
- yield image.filepath
-
- @staticmethod
- def eachEnalbeTexturePath(m):
- for i, slot in enumerate(m.texture_slots):
- if m.use_textures[i] and slot and slot.texture:
- texture=slot.texture
- if texture.type=="IMAGE":
- image=texture.image
- if not image:
- continue
- yield image.filepath
-
-
-class mesh:
- @staticmethod
- def create(name):
- global SCENE
- mesh=bpy.data.meshes.new("Mesh")
- mesh_object= bpy.data.objects.new(name, mesh)
- SCENE.objects.link(mesh_object)
- return mesh, mesh_object
-
- @staticmethod
- def addGeometry(mesh, vertices, faces):
- mesh.from_pydata(vertices, [], faces)
- """
- mesh.add_geometry(len(vertices), 0, len(faces))
- # add vertex
- unpackedVertices=[]
- for v in vertices:
- unpackedVertices.extend(v)
- mesh.vertices.foreach_set("co", unpackedVertices)
- # add face
- unpackedFaces = []
- for face in faces:
- if len(face) == 4:
- if face[3] == 0:
- # rotate indices if the 4th is 0
- face = [face[3], face[0], face[1], face[2]]
- elif len(face) == 3:
- if face[2] == 0:
- # rotate indices if the 3rd is 0
- face = [face[2], face[0], face[1], 0]
- else:
- face.append(0)
- unpackedFaces.extend(face)
- mesh.faces.foreach_set("verts_raw", unpackedFaces)
- """
- assert(len(vertices)==len(mesh.vertices))
- assert(len(faces)==len(mesh.faces))
-
- @staticmethod
- def hasUV(mesh):
- return mesh.active_uv_texture
-
- @staticmethod
- def useVertexUV(mesh):
- pass
-
- @staticmethod
- def addUV(mesh):
- mesh.uv_textures.new()
-
- @staticmethod
- def hasFaceUV(mesh, i, face):
- return mesh.active_uv_texture and mesh.active_uv_texture.data[i]
-
- @staticmethod
- def getFaceUV(mesh, i, faces, count=3):
- if mesh.active_uv_texture and mesh.active_uv_texture.data[i]:
- uvFace=mesh.active_uv_texture.data[i]
- if count==3:
- return (uvFace.uv1, uvFace.uv2, uvFace.uv3)
- elif count==4:
- return (uvFace.uv1, uvFace.uv2, uvFace.uv3, uvFace.uv4)
- else:
- print(count)
- assert(False)
- else:
- return ((0, 0), (0, 0), (0, 0), (0, 0))
-
- @staticmethod
- def setFaceUV(m, i, face, uv_array, image):
- uv_face=m.uv_textures[0].data[i]
- uv_face.uv=uv_array
- if image:
- uv_face.image=image
- uv_face.use_image=True
-
- @staticmethod
- def vertsDelete(m, remove_vertices):
- enterEditMode()
- bpy.ops.mesh.select_all(action='DESELECT')
- enterObjectMode()
-
- for i in remove_vertices:
- m.vertices[i].select=True
-
- enterEditMode()
- bpy.ops.mesh.delete(type='VERT')
- enterObjectMode()
-
- @staticmethod
- def setSmooth(m, smoothing):
- m.auto_smooth_angle=int(smoothing)
- m.use_auto_smooth=True
-
- @staticmethod
- def recalcNormals(mesh_object):
- bpy.ops.object.select_all(action='DESELECT')
- object.activate(mesh_object)
- enterEditMode()
- bpy.ops.mesh.normals_make_consistent()
- enterObjectMode()
-
- @staticmethod
- def flipNormals(m):
- m.flipNormals()
-
- @staticmethod
- def addMaterial(m, material):
- m.materials.append(material)
-
- @staticmethod
- def getMaterial(m, index):
- return m.materials[index]
-
-
-class vertex:
- @staticmethod
- def setNormal(v, normal):
- v.normal=mathutils.Vector(normal)
-
- @staticmethod
- def getNormal(v):
- return v.normal
-
- @staticmethod
- def setUv(v, uv):
- # sticky ?
- pass
-
-
-class face:
- @staticmethod
- def getVertexCount(face):
- return len(face.vertices)
-
- @staticmethod
- def getVertices(face):
- return face.vertices[:]
-
- @staticmethod
- def getIndices(face, count=3):
- if count==3:
- return [face.vertices[0], face.vertices[1], face.vertices[2]]
- elif count==4:
- return [face.vertices[0], face.vertices[1], face.vertices[2], face.vertices[3]]
- else:
- assert(False)
-
- @staticmethod
- def setMaterial(face, material_index):
- face.material_index=material_index
-
- @staticmethod
- def getMaterialIndex(face):
- return face.material_index
-
- @staticmethod
- def setNormal(face, normal):
- face.normal=normal
-
- @staticmethod
- def getNormal(face):
- return face.normal
-
- @staticmethod
- def setSmooth(face, isSmooth):
- face.use_smooth=True if isSmooth else False
-
-
-class armature:
- @staticmethod
- def create():
- global SCENE
- armature = bpy.data.armatures.new('Armature')
- armature_object=bpy.data.objects.new('Armature', armature)
- SCENE.objects.link(armature_object)
-
- armature_object.show_x_ray=True
- armature.show_names=True
- #armature.draw_type='OCTAHEDRAL'
- armature.draw_type='STICK'
- armature.use_deform_envelopes=False
- armature.use_deform_vertex_groups=True
- armature.use_mirror_x=True
-
- return armature, armature_object
-
- @staticmethod
- def makeEditable(armature_object):
- global SCENE
- # select only armature object and set edit mode
- SCENE.objects.active=armature_object
- bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
- bpy.ops.object.mode_set(mode='EDIT', toggle=False)
-
- @staticmethod
- def createIkConstraint(armature_object, p_bone, effector_name, ik):
- constraint = p_bone.constraints.new('IK')
- constraint.chain_count=len(ik.children)
- constraint.target=armature_object
- constraint.subtarget=effector_name
- constraint.use_tail=False
- # not used. place folder when export.
- constraint.weight=ik.weight
- constraint.iterations=ik.iterations * 10
- return constraint
-
- @staticmethod
- def createBone(armature, name):
- return armature.edit_bones.new(name)
-
- @staticmethod
- def update(armature):
- pass
-
-
-class bone:
- @staticmethod
- def setConnected(bone):
- bone.use_connect=True
-
- @staticmethod
- def isConnected(b):
- return b.connected
-
- @staticmethod
- def setLayerMask(bone, layers):
- layer=[]
- for i in range(32):
- try:
- layer.append(True if layers[i]!=0 else False)
- except IndexError:
- layer.append(False)
- bone.layers=layer
-
- @staticmethod
- def getHeadLocal(b):
- return b.head_local[0:3]
-
- @staticmethod
- def getTailLocal(b):
- return b.tail_local[0:3]
-
-
-class constraint:
- @staticmethod
- def ikChainLen(c):
- return c.chain_length
-
- @staticmethod
- def ikTarget(c):
- return c.subtarget
-
- @staticmethod
- def ikItration(c):
- return c.iterations
-
- @staticmethod
- def ikRotationWeight(c):
- return c.weight
-
- @staticmethod
- def isIKSolver(c):
- return c.type=='IK'
-
+++ /dev/null
-#!BPY
-# coding: utf-8
-
-"""
-Name: 'Metasequoia (.mqo)...'
-Blender: 245
-Group: 'Export'
-Tooltip: 'Save as Metasequoia MQO File'
-"""
-__author__= 'ousttrue'
-__url__ = ["http://gunload.web.fc2.com/blender/"]
-__version__= '2.2'
-__bpydoc__ = """\
-This script is an exporter to MQO file format.
-
-Usage:
-
-Run this script from "File->Export" menu.
-
-0.1 20080128:
-0.2 20100518: refactoring.
-0.3 20100606: integrate 2.4 and 2.5.
-0.4 20100626: refactoring.
-0.5 20100710: add [apply_modifier] option(2.5 only).
-0.6 20100714: remove shape_key when apply_modifier. fix material.
-2.0 20100724: update for Blender2.53.
-2.1 20101005: update for Blender2.54.
-2.2 20101228: update for Blender2.55.
-"""
-
-bl_addon_info = {
- 'category': 'Import/Export',
- 'name': 'Export: Metasequioa Model Format (.mqo)',
- 'author': 'ousttrue',
- 'version': (2, 1),
- 'blender': (2, 5, 3),
- 'location': 'File > Export',
- 'description': 'Export to the Metasequioa Model Format (.mqo)',
- 'warning': '', # used for warning icon and text in addons panel
- 'wiki_url': 'http://sourceforge.jp/projects/meshio/wiki/FrontPage',
- 'tracker_url': 'http://sourceforge.jp/ticket/newticket.php?group_id=5081',
- }
-
-import os
-import sys
-
-def isBlender24():
- return sys.version_info[0]<3
-
-
-class MQOMaterial(object):
- __slots__=[
- 'name', 'shader', 'r', 'g', 'b', 'a',
- 'dif', 'amb', 'emi',
- ]
- def __init__(self, name, shader=3):
- self.name=name
- self.shader=shader
- self.r=0.5
- self.g=0.5
- self.b=0.5
- self.a=1
- self.dif=1
- self.amb=0
- self.emi=0
-
- def __str__(self):
- return "\"%s\" shader(%d) col(%f %f %f %f) dif(%f) amb(%f) emi(%f)" % (
- self.name, self.shader, self.r, self.g, self.b, self.a,
- self.dif, self.amb, self.emi
- )
-
-
-if isBlender24():
- # for 2.4
- import Blender
- from Blender import Mathutils
- import bpy
-
- # wrapper
- import bl24 as bl
-
- def materialToMqo(m):
- material=MQOMaterial(m.name, 3)
- material.r=m.rgbCol[0]
- material.g=m.rgbCol[1]
- material.b=m.rgbCol[2]
- material.a=m.alpha
- return material
-
-else:
- # for 2.5
- import bpy
-
- # wrapper
- import bl25 as bl
-
- def materialToMqo(m):
- material=MQOMaterial(m.name, 3)
- material.r=m.diffuse_color[0]
- material.g=m.diffuse_color[1]
- material.b=m.diffuse_color[2]
- material.a=m.alpha
- material.amb=m.ambient
- material.emi=m.emit
- return material
-
-def apply_transform(vec, matrix):
- x, y, z = vec
- xloc, yloc, zloc = matrix[3][0], matrix[3][1], matrix[3][2]
- return x*matrix[0][0] + y*matrix[1][0] + z*matrix[2][0] + xloc,\
- x*matrix[0][1] + y*matrix[1][1] + z*matrix[2][1] + yloc,\
- x*matrix[0][2] + y*matrix[1][2] + z*matrix[2][2] + zloc
-
-def convert_to_mqo(vec):
- return vec.x, vec.z, -vec.y
-
-
-class OutlineNode(object):
- __slots__=['o', 'children']
- def __init__(self, o):
- self.o=o
- self.children=[]
-
- def __str__(self):
- return "<Node %s>" % self.o
-
-
-class ObjectInfo(object):
- __slots__=['object', 'depth', 'material_map']
- def __init__(self, o, depth):
- self.object=o
- self.depth=depth
- self.material_map={}
-
- def __str__(self):
- return "<ObjectInfo %d %s>" % (self.depth, self.object)
-
-
-class MqoExporter(object):
- __slots__=["materials", "objects", 'scale', 'apply_modifier',]
- def __init__(self, scale, apply_modifier):
- self.objects=[]
- self.materials=[]
- self.scale=scale
- self.apply_modifier=apply_modifier
-
- def setup(self, scene):
- # 木構造を構築する
- object_node_map={}
- for o in scene.objects:
- object_node_map[o]=OutlineNode(o)
- for node in object_node_map.values():
- if node.o.parent:
- object_node_map[node.o.parent].children.append(node)
-
- # ルートを得る
- root=object_node_map[scene.objects.active]
-
- # 情報を集める
- if root.o.type.upper()=='EMPTY':
- # depth調整
- for node in root.children:
- self.__setup(node)
- else:
- self.__setup(root)
-
- def __setup(self, node, depth=0):
- info=ObjectInfo(node.o, depth)
- self.objects.append(info)
- if node.o.type.upper()=='MESH':
- # set material index
- for i, m in enumerate(node.o.data.materials):
- info.material_map[i]=self.__getOrAddMaterial(m)
- # recursive
- for child in node.children:
- self.__setup(child, depth+1)
-
- def __getOrAddMaterial(self, material):
- for i, m in enumerate(self.materials):
- if m==material:
- return i
- index=len(self.materials)
- self.materials.append(material)
- return index
-
- def write(self, path):
- bl.message("open: "+path)
- io=bl.Writer(path, 'cp932')
- self.__write_header(io)
- self.__write_scene(io)
- print("Writing MaterialChunk")
- self.__write_materials(io, os.path.dirname(path))
- print("Writing ObjectChunk")
- for info in self.objects:
- self.__write_object(io, info)
- io.write("Eof\r\n")
- io.flush()
- io.close()
-
- def __write_header(self, io):
- io.write("Metasequoia Document\r\n")
- io.write("Format Text Ver 1.0\r\n")
- io.write("\r\n")
-
- def __write_scene(self, io):
- print("Writing SceneChunk")
- io.write("Scene {\r\n")
- io.write("}\r\n")
-
- def __write_materials(self, io, dirname):
- # each material
- io.write("Material %d {\r\n" % (len(self.materials)))
- for m in self.materials:
- io.write(str(materialToMqo(m)))
- # ToDo separated alpha texture
- for filename in bl.material.eachTexturePath(m):
- if len(dirname)>0 and filename.startswith(dirname):
- # 相対パスに変換する
- filename=filename[len(dirname)+1:]
- io.write(" tex(\"%s\")" % filename)
- break
- io.write("\r\n")
- # end of chunk
- io.write("}\r\n")
-
- def __write_object(self, io, info):
- print(info)
-
- obj=info.object
- if obj.type.upper()=='MESH' or obj.type.upper()=='EMPTY':
- pass
- else:
- print(obj.type)
- return
-
- io.write("Object \""+obj.name+"\" {\r\n")
-
- # depth
- io.write("\tdepth %d\r\n" % info.depth)
-
- # mirror
- if not self.apply_modifier:
- if bl.modifier.hasType(obj, 'MIRROR'):
- io.write("\tmirror 1\r\n")
- io.write("\tmirror_axis 1\r\n")
-
- if obj.type.upper()=='MESH':
- # duplicate and applyMatrix
- copyMesh, copyObj=bl.object.duplicate(obj)
- # apply transform
- copyObj.scale=obj.scale
- bpy.ops.object.scale_apply()
- copyObj.rotation_euler=obj.rotation_euler
- bpy.ops.object.rotation_apply()
- copyObj.location=obj.location
- bpy.ops.object.location_apply()
- # apply modifier
- if self.apply_modifier:
- # remove shape key
- while bl.object.hasShapeKey(copyObj):
- bpy.ops.object.shape_key_remove()
- for m in [m for m in copyObj.modifiers]:
- if m.type=='SOLIDFY':
- continue
- elif m.type=='ARMATURE':
- bpy.ops.object.modifier_apply(modifier=m.name)
- elif m.type=='MIRROR':
- bpy.ops.object.modifier_apply(modifier=m.name)
- else:
- print(m.type)
- # write mesh
- self.__write_mesh(io, copyMesh, info.material_map)
- bl.object.delete(copyObj)
-
- io.write("}\r\n") # end of object
-
- def __write_mesh(self, io, mesh, material_map):
- # vertices
- io.write("\tvertex %d {\r\n" % len(mesh.verts))
- for vert in mesh.verts:
- x, y, z = convert_to_mqo(vert.co)
- io.write("\t\t%f %f %f\r\n" %
- (x*self.scale, y*self.scale, z*self.scale)) # rotate to y-up
- io.write("\t}\r\n")
-
- # faces
- io.write("\tface %d {\r\n" % len(mesh.faces))
- for i, face in enumerate(mesh.faces):
- count=bl.face.getVertexCount(face)
- # V
- io.write("\t\t%d V(" % count)
- for j in reversed(bl.face.getVertices(face)):
- io.write("%d " % j)
- io.write(")")
- # mat
- if len(mesh.materials):
- io.write(" M(%d)" %
- material_map[bl.face.getMaterialIndex(face)])
- # UV
- if bl.mesh.hasUV(mesh) and bl.mesh.hasFaceUV(mesh, i, face):
- io.write(" UV(")
- for uv in reversed(bl.mesh.getFaceUV(mesh, i, face, count)):
- # reverse vertical value
- io.write("%f %f " % (uv[0], 1.0-uv[1]))
- io.write(")")
- io.write("\r\n")
- io.write("\t}\r\n") # end of faces
-
-
-def __execute(filename, scene, scale=10, apply_modifier=False):
- if scene.objects.active:
- exporter=MqoExporter(scale, apply_modifier)
- exporter.setup(scene)
- exporter.write(filename)
- else:
- bl.message('no active object !')
-
-
-if isBlender24():
- # for 2.4
- def execute_24(filename):
- scene=Blender.Scene.GetCurrent()
- bl.initialize('mqo_export', scene)
- __execute(
- filename.decode(bl.INTERNAL_ENCODING),
- scene, False)
- bl.finalize()
-
- # execute
- Blender.Window.FileSelector(
- execute_24,
- 'Export Metasequoia MQO',
- Blender.sys.makename(ext='.mqo'))
-
-else:
- # for 2.5
- def execute_25(path, scene, scale, apply_modifier):
- bl.initialize('mqo_export', scene)
- __execute(path, scene, scale, apply_modifier)
- bl.finalize()
-
- # operator
- class EXPORT_OT_mqo(bpy.types.Operator):
- '''Save a Metasequoia MQO file.'''
- bl_idname = "export_scene.mqo"
- bl_label = 'Export MQO'
-
- # List of operator properties, the attributes will be assigned
- # to the class instance from the operator settings before calling.
- filepath = bpy.props.StringProperty()
- filename = bpy.props.StringProperty()
- directory = bpy.props.StringProperty()
-
- scale = bpy.props.FloatProperty(
- name="Scale",
- description="Scale the MQO by this value",
- min=0.0001, max=1000000.0,
- soft_min=0.001, soft_max=100.0, default=10.0)
-
- apply_modifier = bpy.props.BoolProperty(
- name="ApplyModifier",
- description="Would apply modifiers",
- default=False)
-
- def execute(self, context):
- execute_25(
- self.properties.filepath,
- context.scene,
- self.properties.scale,
- self.properties.apply_modifier)
- return 'FINISHED'
-
- def invoke(self, context, event):
- wm=context.window_manager
- try:
- wm.fileselect_add(self)
- except:
- wm.add_fileselect(self)
- return 'RUNNING_MODAL'
-
- # register menu
- def menu_func(self, context):
- default_path=bpy.data.filepath.replace(".blend", ".mqo")
- self.layout.operator(
- EXPORT_OT_mqo.bl_idname,
- text="Metasequoia (.mqo)",
- icon='PLUGIN'
- ).filepath=default_path
-
- def register():
- bpy.types.INFO_MT_file_export.append(menu_func)
-
- def unregister():
- bpy.types.INFO_MT_file_export.remove(menu_func)
-
- if __name__ == "__main__":
- register()
-
+++ /dev/null
-#!BPY\r
-# coding: utf-8\r
-""" \r
-Name: 'Metasequoia(.mqo)...'\r
-Blender: 245\r
-Group: 'Import'\r
-Tooltip: 'Import from Metasequoia file format (.mqo)'\r
-"""\r
-__author__=['ousttrue']\r
-__url__ = ["http://gunload.web.fc2.com/blender/"]\r
-__version__= '2.2'\r
-__bpydoc__= '''\\r
-\r
-MQO Importer\r
-\r
-This script imports a mqo into Blender for editing.\r
-\r
-0.2 20080123: update.\r
-0.3 20091125: modify for linux.\r
-0.4 20100310: rewrite.\r
-0.5 20100311: create armature from mikoto bone.\r
-0.6 20100505: C extension.\r
-0.7 20100606: integrate 2.4 and 2.5.\r
-0.8 20100619: fix multibyte object name.\r
-0.9 20100626: refactoring.\r
-2.0 20100724: update for Blender2.53.\r
-2.1 20100731: add full python module.\r
-2.2 20101005: update for Blender2.54.\r
-2.3 20101228: update for Blender2.55.\r
-'''\r
-\r
-bl_addon_info = {\r
- 'category': 'Import/Export',\r
- 'name': 'Import: Metasequioa Model Format (.mqo)',\r
- 'author': 'ousttrue',\r
- 'version': (2, 0),\r
- 'blender': (2, 5, 3),\r
- 'location': 'File > Import',\r
- 'description': 'Import from the Metasequioa Model Format (.mqo)',\r
- 'warning': '', # used for warning icon and text in addons panel\r
- 'wiki_url': 'http://sourceforge.jp/projects/meshio/wiki/FrontPage',\r
- 'tracker_url': 'http://sourceforge.jp/ticket/newticket.php?group_id=5081',\r
- }\r
-\r
-import os\r
-import sys\r
-\r
-try:\r
- # C extension\r
- from meshio import mqo\r
- print('use meshio C module')\r
-except ImportError:\r
- # full python\r
- from pymeshio import mqo\r
-\r
-def isBlender24():\r
- return sys.version_info[0]<3\r
-\r
-if isBlender24():\r
- # for 2.4\r
- import Blender\r
- from Blender import Mathutils\r
- import bpy\r
-\r
- # wrapper\r
- import bl24 as bl\r
-\r
- def createMqoMaterial(m):\r
- material = Blender.Material.New(\r
- m.getName().encode(bl.INTERNAL_ENCODING))\r
- #material.mode |= Blender.Material.Modes.SHADELESS\r
- # diffuse\r
- material.rgbCol = [m.color.r, m.color.g, m.color.b]\r
- material.alpha = m.color.a\r
- # other\r
- material.amb=m.ambient\r
- material.spec=m.specular\r
- material.hard=int(255 * m.power)\r
- material.emit=m.emit\r
- return material\r
-\r
-else:\r
- # for 2.5\r
- import bpy\r
-\r
- # wrapper\r
- import bl25 as bl\r
-\r
- def createMqoMaterial(m):\r
- material = bpy.data.materials.new(m.getName())\r
- # shader\r
- if m.shader==1:\r
- material.diffuse_shader='FRESNEL'\r
- else:\r
- material.diffuse_shader='LAMBERT'\r
- # diffuse\r
- material.diffuse_color=[m.color.r, m.color.g, m.color.b]\r
- material.diffuse_intensity=m.diffuse\r
- material.alpha=m.color.a\r
- # other\r
- material.ambient = m.ambient\r
- #material.specular = m.specular\r
- material.emit=m.emit\r
- material.use_shadeless=True\r
- return material\r
-\r
-\r
-def has_mikoto(mqo):\r
- #for o in mqo.objects:\r
- # if o.getName().startswith('bone'):\r
- # return True\r
- # if o.getName().startswith('sdef'):\r
- # return True\r
- # if o.getName().startswith('anchor'):\r
- # return True\r
- return False\r
-\r
-\r
-def __createMaterials(mqo, directory):\r
- """\r
- create blender materials and renturn material list.\r
- """\r
- materials = []\r
- textureMap={}\r
- imageMap={}\r
- if len(mqo.materials)>0:\r
- for material_index, m in enumerate(mqo.materials):\r
- # material\r
- material=createMqoMaterial(m)\r
- materials.append(material)\r
- # texture\r
- texture_name=m.getTexture()\r
- if texture_name!='':\r
- if texture_name in textureMap:\r
- texture=textureMap[texture_name]\r
- else:\r
- # load texture image\r
- if os.path.isabs(texture_name):\r
- # absolute\r
- path = texture_name\r
- else:\r
- # relative\r
- path = os.path.join(directory, texture_name)\r
- # texture\r
- path=path.replace("\\", "/")\r
- if os.path.exists(path):\r
- print("create texture:", path)\r
- texture, image=bl.texture.create(path)\r
- textureMap[texture_name]=texture\r
- imageMap[material_index]=image\r
- else:\r
- print("%s not exits" % path)\r
- continue\r
- bl.material.addTexture(material, texture)\r
- else:\r
- # default material\r
- pass\r
- return materials, imageMap\r
-\r
-\r
-def __createObjects(mqo, root, materials, imageMap, scale):\r
- """\r
- create blender mesh objects.\r
- """\r
- # tree stack\r
- stack=[root] \r
- objects=[]\r
- for o in mqo.objects:\r
- mesh, mesh_object=bl.mesh.create(o.getName())\r
-\r
- # add hierarchy\r
- stack_depth=len(stack)-1\r
- #print(o.depth, stack_depth)\r
- if o.depth<stack_depth:\r
- for i in range(stack_depth-o.depth):\r
- stack.pop()\r
- bl.object.makeParent(stack[-1], mesh_object)\r
- stack.append(mesh_object)\r
-\r
- if o.getName().startswith('sdef'):\r
- objects.append(mesh_object)\r
- elif o.getName().startswith('anchor'):\r
- bl.object.setLayerMask(mesh_object, [0, 1])\r
- elif o.getName().startswith('bone'):\r
- bl.object.setLayerMask(mesh_object, [0, 1])\r
-\r
- # geometry\r
- vertices=[(v.x * scale, -v.z * scale, v.y * scale) for v in o.vertices]\r
- faces=[]\r
- materialMap={}\r
- for f in o.faces:\r
- face_indices=[]\r
- # flip face\r
- for i in reversed(range(f.index_count)):\r
- face_indices.append(f.getIndex(i))\r
- faces.append(face_indices)\r
- materialMap[f.material_index]=True\r
- bl.mesh.addGeometry(mesh, vertices, faces)\r
-\r
- # blender limits 16 materials per mesh\r
- for i, material_index in enumerate(materialMap.keys()):\r
- if i>=16:\r
- # split a mesh ?\r
- print("over 16 materials!")\r
- break\r
- bl.mesh.addMaterial(mesh, materials[material_index])\r
- materialMap[material_index]=i\r
- \r
- # set face params\r
- assert(len(o.faces)==len(mesh.faces))\r
- bl.mesh.addUV(mesh)\r
- for i, (f, face) in enumerate(zip(o.faces, mesh.faces)):\r
- uv_array=[]\r
- # ToDo FIX\r
- # flip face\r
- for j in reversed(range(f.index_count)):\r
- uv_array.append((f.getUV(j).x, 1.0-f.getUV(j).y))\r
- bl.mesh.setFaceUV(mesh, i, face, uv_array, \r
- imageMap.get(f.material_index, None))\r
- if f.material_index in materialMap:\r
- bl.face.setMaterial(face, materialMap[f.material_index])\r
- bl.face.setSmooth(face, True)\r
-\r
- # mirror modifier\r
- if o.mirror:\r
- bl.modifier.addMirror(mesh_object)\r
-\r
- # set smoothing\r
- bl.mesh.setSmooth(mesh, o.smoothing)\r
-\r
- # calc normal\r
- bl.mesh.recalcNormals(mesh_object)\r
-\r
- return objects\r
-\r
-\r
-###############################################################################\r
-# for mqo mikoto bone.\r
-###############################################################################\r
-class MikotoBone(object):\r
- __slots__=[\r
- 'name',\r
- 'iHead', 'iTail', 'iUp',\r
- 'vHead', 'vTail', 'vUp',\r
- 'parent', 'isFloating',\r
- 'children',\r
- ]\r
- def __init__(self, face=None, vertices=None, materials=None):\r
- self.parent=None\r
- self.isFloating=False\r
- self.children=[]\r
- if not face:\r
- self.name='root'\r
- return\r
-\r
- self.name=materials[face.material_index].name.encode('utf-8')\r
-\r
- i0=face.getIndex(0)\r
- i1=face.getIndex(1)\r
- i2=face.getIndex(2)\r
- v0=vertices[i0]\r
- v1=vertices[i1]\r
- v2=vertices[i2]\r
- e01=v1-v0\r
- e12=v2-v1\r
- e20=v0-v2\r
- sqNorm0=e01.getSqNorm()\r
- sqNorm1=e12.getSqNorm()\r
- sqNorm2=e20.getSqNorm()\r
- if sqNorm0>sqNorm1:\r
- if sqNorm1>sqNorm2:\r
- # e01 > e12 > e20\r
- self.iHead=i2\r
- self.iTail=i1\r
- self.iUp=i0\r
- else:\r
- if sqNorm0>sqNorm2:\r
- # e01 > e20 > e12\r
- self.iHead=i2\r
- self.iTail=i0\r
- self.iUp=i1\r
- else:\r
- # e20 > e01 > e12\r
- self.iHead=i1\r
- self.iTail=i0\r
- self.iUp=i2\r
- else:\r
- # 0 < 1\r
- if sqNorm1<sqNorm2:\r
- # e20 > e12 > e01\r
- self.iHead=i1\r
- self.iTail=i2\r
- self.iUp=i0\r
- else:\r
- if sqNorm0<sqNorm2:\r
- # e12 > e20 > e01\r
- self.iHead=i0\r
- self.iTail=i2\r
- self.iUp=i1\r
- else:\r
- # e12 > e01 > e20\r
- self.iHead=i0\r
- self.iTail=i1\r
- self.iUp=i2\r
- self.vHead=vertices[self.iHead]\r
- self.vTail=vertices[self.iTail]\r
- self.vUp=vertices[self.iUp]\r
-\r
- if self.name.endswith('[]'):\r
- basename=self.name[0:-2]\r
- # expand LR name\r
- if self.vTail.x>0:\r
- self.name="%s_L" % basename\r
- else:\r
- self.name="%s_R" % basename\r
-\r
-\r
- def setParent(self, parent, floating=False):\r
- if floating:\r
- self.isFloating=True\r
- self.parent=parent\r
- parent.children.append(self)\r
-\r
- def printTree(self, indent=''):\r
- print("%s%s" % (indent, self.name))\r
- for child in self.children:\r
- child.printTree(indent+' ')\r
-\r
-\r
-def build_armature(armature, mikotoBone, parent=None):\r
- """\r
- create a armature bone.\r
- """\r
- bone = Armature.Editbone()\r
- bone.name = mikotoBone.name.encode('utf-8')\r
- armature.bones[bone.name] = bone\r
-\r
- bone.head = Mathutils.Vector(*mikotoBone.vHead.to_a())\r
- bone.tail = Mathutils.Vector(*mikotoBone.vTail.to_a())\r
- if parent:\r
- bone.parent=parent\r
- if mikotoBone.isFloating:\r
- pass\r
- else:\r
- bone.options=[Armature.CONNECTED]\r
-\r
- for child in mikotoBone.children:\r
- build_armature(armature, child, bone)\r
-\r
-\r
-def create_armature(mqo):\r
- """\r
- create armature\r
- """\r
- boneObject=None\r
- for o in mqo.objects:\r
- if o.name.startswith('bone'):\r
- boneObject=o\r
- break\r
- if not boneObject:\r
- return\r
-\r
- tailMap={}\r
- for f in boneObject.faces:\r
- if f.index_count!=3:\r
- print("invalid index_count: %d" % f.index_count)\r
- continue\r
- b=MikotoBone(f, boneObject.vertices, mqo.materials)\r
- tailMap[b.iTail]=b\r
-\r
- #################### \r
- # build mikoto bone tree\r
- #################### \r
- mikotoRoot=MikotoBone()\r
-\r
- for b in tailMap.values():\r
- # each bone has unique parent or is root bone.\r
- if b.iHead in tailMap:\r
- b.setParent(tailMap[b.iHead])\r
- else: \r
- isFloating=False\r
- for e in boneObject.edges:\r
- if b.iHead==e.indices[0]:\r
- # floating bone\r
- if e.indices[1] in tailMap:\r
- b.setParent(tailMap[e.indices[1]], True)\r
- isFloating=True\r
- break\r
- elif b.iHead==e.indices[1]:\r
- # floating bone\r
- if e.indices[0] in tailMap:\r
- b.setParent(tailMap[e.indices[0]], True)\r
- isFloating=True\r
- break\r
- if isFloating:\r
- continue\r
-\r
- # no parent bone\r
- b.setParent(mikotoRoot, True)\r
-\r
- if len(mikotoRoot.children)==0:\r
- print("no root bone")\r
- return\r
-\r
- if len(mikotoRoot.children)==1:\r
- # single root\r
- mikotoRoot=mikotoRoot.children[0]\r
- mikotoRoot.parent=None\r
- else:\r
- mikotoRoot.vHead=Vector3(0, 10, 0)\r
- mikotoRoot.vTail=Vector3(0, 0, 0)\r
-\r
- #################### \r
- # create armature\r
- #################### \r
- armature = Armature.New()\r
- # link to object\r
- armature_object = scene.objects.new(armature)\r
- # create action\r
- act = Armature.NLA.NewAction()\r
- act.setActive(armature_object)\r
- # set XRAY\r
- armature_object.drawMode |= Object.DrawModes.XRAY\r
- # armature settings\r
- armature.drawType = Armature.OCTAHEDRON\r
- armature.envelopes = False\r
- armature.vertexGroups = True\r
- armature.mirrorEdit = True\r
- armature.drawNames=True\r
-\r
- # edit bones\r
- armature.makeEditable()\r
- build_armature(armature, mikotoRoot)\r
- armature.update()\r
-\r
- return armature_object\r
- \r
-\r
-class TrianglePlane(object):\r
- """\r
- mikoto\e$BJ}<0%\!<%s$N%"%s%+!<%&%'%$%H7W;;MQ!#\e(B\r
- (\e$BIT40A4\e(B)\r
- """\r
- __slots__=['normal', \r
- 'v0', 'v1', 'v2',\r
- ]\r
- def __init__(self, v0, v1, v2):\r
- self.v0=v0\r
- self.v1=v1\r
- self.v2=v2\r
-\r
- def isInsideXY(self, p):\r
- v0=Vector2(self.v0.x, self.v0.y)\r
- v1=Vector2(self.v1.x, self.v1.y)\r
- v2=Vector2(self.v2.x, self.v2.y)\r
- e01=v1-v0\r
- e12=v2-v1\r
- e20=v0-v2\r
- c0=Vector2.cross(e01, p-v0)\r
- c1=Vector2.cross(e12, p-v1)\r
- c2=Vector2.cross(e20, p-v2)\r
- if c0>=0 and c1>=0 and c2>=0:\r
- return True\r
- if c0<=0 and c1<=0 and c2<=0:\r
- return True\r
-\r
- def isInsideYZ(self, p):\r
- v0=Vector2(self.v0.y, self.v0.z)\r
- v1=Vector2(self.v1.y, self.v1.z)\r
- v2=Vector2(self.v2.y, self.v2.z)\r
- e01=v1-v0\r
- e12=v2-v1\r
- e20=v0-v2\r
- c0=Vector2.cross(e01, p-v0)\r
- c1=Vector2.cross(e12, p-v1)\r
- c2=Vector2.cross(e20, p-v2)\r
- if c0>=0 and c1>=0 and c2>=0:\r
- return True\r
- if c0<=0 and c1<=0 and c2<=0:\r
- return True\r
-\r
- def isInsideZX(self, p):\r
- v0=Vector2(self.v0.z, self.v0.x)\r
- v1=Vector2(self.v1.z, self.v1.x)\r
- v2=Vector2(self.v2.z, self.v2.x)\r
- e01=v1-v0\r
- e12=v2-v1\r
- e20=v0-v2\r
- c0=Vector2.cross(e01, p-v0)\r
- c1=Vector2.cross(e12, p-v1)\r
- c2=Vector2.cross(e20, p-v2)\r
- if c0>=0 and c1>=0 and c2>=0:\r
- return True\r
- if c0<=0 and c1<=0 and c2<=0:\r
- return True\r
-\r
-\r
-class MikotoAnchor(object):\r
- """\r
- mikoto\e$BJ}<0%9%1%k%H%s$N%"%s%+!<!#\e(B\r
- """\r
- __slots__=[\r
- "triangles", "bbox",\r
- ]\r
- def __init__(self):\r
- self.triangles=[]\r
- self.bbox=None\r
-\r
- def push(self, face, vertices):\r
- if face.index_count==3:\r
- self.triangles.append(TrianglePlane(\r
- vertices[face.indices[0]],\r
- vertices[face.indices[1]],\r
- vertices[face.indices[2]]\r
- ))\r
- elif face.index_count==4:\r
- self.triangles.append(TrianglePlane(\r
- vertices[face.indices[0]],\r
- vertices[face.indices[1]],\r
- vertices[face.indices[2]]\r
- ))\r
- self.triangles.append(TrianglePlane(\r
- vertices[face.indices[2]],\r
- vertices[face.indices[3]],\r
- vertices[face.indices[0]]\r
- ))\r
- # bounding box\r
- if not self.bbox:\r
- self.bbox=BoundingBox(vertices[face.indices[0]])\r
- for i in face.indices:\r
- self.bbox.expand(vertices[i])\r
-\r
-\r
- def calcWeight(self, v):\r
- if not self.bbox.isInside(v):\r
- return 0\r
-\r
- if self.anyXY(v.x, v.y) and self.anyYZ(v.y, v.z) and self.anyZX(v.z, v.x):\r
- return 1.0\r
- else:\r
- return 0\r
- \r
- def anyXY(self, x, y):\r
- for t in self.triangles:\r
- if t.isInsideXY(Vector2(x, y)):\r
- return True\r
- return False\r
-\r
- def anyYZ(self, y, z):\r
- for t in self.triangles:\r
- if t.isInsideYZ(Vector2(y, z)):\r
- return True\r
- return False\r
-\r
- def anyZX(self, z, x):\r
- for t in self.triangles:\r
- if t.isInsideZX(Vector2(z, x)):\r
- return True\r
- return False\r
-\r
-\r
-def create_bone_weight(scene, mqo, armature_object, objects):\r
- """\r
- create mikoto bone weight.\r
- """\r
- anchorMap={}\r
- # setup mikoto anchors\r
- for o in mqo.objects:\r
- if o.name.startswith("anchor"):\r
- for f in o.faces:\r
- name=mqo.materials[f.material_index].name\r
- if name.endswith('[]'):\r
- basename=name[0:-2]\r
- v=o.vertices[f.indices[0]]\r
- if(v.x>0):\r
- # L\r
- name_L=basename+'_L'\r
- if not name_L in anchorMap:\r
- anchorMap[name_L]=MikotoAnchor()\r
- anchorMap[name_L].push(f, o.vertices)\r
- elif(v.x<0):\r
- # R\r
- name_R=basename+'_R'\r
- if not name_R in anchorMap:\r
- anchorMap[name_R]=MikotoAnchor()\r
- anchorMap[name_R].push(f, o.vertices)\r
- else:\r
- print("no side", v)\r
- else:\r
- if not name in anchorMap:\r
- anchorMap[name]=MikotoAnchor()\r
- anchorMap[name].push(f, o.vertices)\r
-\r
- for o in objects:\r
- # add armature modifier\r
- mod=o.modifiers.append(Modifier.Types.ARMATURE)\r
- mod[Modifier.Settings.OBJECT] = armature_object\r
- mod[Modifier.Settings.ENVELOPES] = False\r
- o.makeDisplayList()\r
- # create vertex group\r
- mesh=o.getData(mesh=True)\r
- for name in anchorMap.keys():\r
- mesh.addVertGroup(name)\r
- mesh.update()\r
- \r
- # assing vertices to vertex group\r
- for o in objects:\r
- mesh=o.getData(mesh=True)\r
- for i, mvert in enumerate(mesh.verts):\r
- hasWeight=False\r
- for name, anchor in anchorMap.items():\r
- weight=anchor.calcWeight(mvert.co)\r
- if weight>0:\r
- mesh.assignVertsToGroup(\r
- name, [i], weight, Mesh.AssignModes.ADD)\r
- hasWeight=True\r
- if not hasWeight:\r
- # debug orphan vertex\r
- print('orphan', mvert)\r
- mesh.update()\r
-\r
-\r
-def __execute(filename, scene, scale=0.1):\r
- # parse file\r
- io=mqo.IO()\r
- if not io.read(filename):\r
- bl.message("fail to load %s" % filename)\r
- return\r
-\r
- # create materials\r
- materials, imageMap=__createMaterials(io, os.path.dirname(filename))\r
- if len(materials)==0:\r
- materials.append(bl.material.create('default'))\r
-\r
- # create objects\r
- root=bl.object.createEmpty(os.path.basename(filename))\r
- objects=__createObjects(io, root, materials, imageMap, scale)\r
-\r
- if has_mikoto(io):\r
- # create mikoto bone\r
- armature_object=create_armature(io)\r
- if armature_object:\r
- root.makeParent([armature_object])\r
-\r
- # create bone weight\r
- create_bone_weight(io, armature_object, objects)\r
-\r
- \r
-###############################################################################\r
-# register\r
-###############################################################################\r
-if isBlender24():\r
- # for 2.4\r
- def execute_24(filename):\r
- scene=Blender.Scene.GetCurrent()\r
- bl.initialize('mqo_import', scene)\r
- __execute(\r
- filename.decode(bl.INTERNAL_ENCODING), \r
- scene)\r
- bl.finalize()\r
-\r
- # execute\r
- Blender.Window.FileSelector(execute_24, 'Import MQO', '*.mqo')\r
-\r
-else:\r
- # for 2.5\r
- def execute_25(filename, scene, scale):\r
- bl.initialize('mqo_import', scene)\r
- __execute(filename, scene, scale)\r
- bl.finalize()\r
-\r
- # operator\r
- class IMPORT_OT_mqo(bpy.types.Operator):\r
- '''Import from Metasequoia file format (.mqo)'''\r
- bl_idname = "import_scene.mqo"\r
- bl_label = 'Import MQO'\r
-\r
- # List of operator properties, the attributes will be assigned\r
- # to the class instance from the operator settings before calling.\r
- filepath = bpy.props.StringProperty()\r
- filename = bpy.props.StringProperty()\r
- directory = bpy.props.StringProperty()\r
-\r
- scale = bpy.props.FloatProperty(\r
- name="Scale", \r
- description="Scale the MQO by this value", \r
- min=0.0001, max=1000000.0, \r
- soft_min=0.001, soft_max=100.0, default=0.1)\r
-\r
- def execute(self, context):\r
- execute_25(\r
- self.properties.filepath, \r
- context.scene, \r
- self.properties.scale)\r
- return 'FINISHED'\r
-\r
- def invoke(self, context, event):\r
- wm=context.window_manager\r
- try:\r
- wm.fileselect_add(self)\r
- except:\r
- wm.add_fileselect(self)\r
- return 'RUNNING_MODAL'\r
-\r
-\r
- # register menu\r
- def menu_func(self, context): \r
- self.layout.operator(\r
- IMPORT_OT_mqo.bl_idname, \r
- text="Metasequoia (.mqo)",\r
- icon='PLUGIN'\r
- )\r
-\r
- def register():\r
- bpy.types.INFO_MT_file_import.append(menu_func)\r
-\r
- def unregister():\r
- bpy.types.INFO_MT_file_import.remove(menu_func)\r
-\r
- if __name__=="__main__":\r
- register()\r
-\r
+++ /dev/null
-#!BPY
-# coding: utf-8
-"""
- Name: 'MikuMikuDance model (.pmd)...'
- Blender: 248
- Group: 'Export'
- Tooltip: 'Export PMD file for MikuMikuDance.'
-"""
-__author__= ["ousttrue"]
-__version__= "2.2"
-__url__=()
-__bpydoc__="""
-pmd Importer
-
-This script exports a pmd model.
-
-0.1 20100318: first implementation.
-0.2 20100519: refactoring. use C extension.
-1.0 20100530: implement basic features.
-1.1 20100612: integrate 2.4 and 2.5.
-1.2 20100616: implement rigid body.
-1.3 20100619: fix rigid body, bone weight.
-1.4 20100626: refactoring.
-1.5 20100629: sphere map.
-1.6 20100710: toon texture & bone group.
-1.7 20100711: separate vertex with normal or uv.
-2.0 20100724: update for Blender2.53.
-2.1 20100731: add full python module.
-2.2 20101005: update for Blender2.54.
-2.3 20101228: update for Blender2.55.
-"""
-
-bl_addon_info = {
- 'category': 'Import/Export',
- 'name': 'Export: MikuMikuDance Model Format (.pmd)',
- 'author': 'ousttrue',
- 'version': (2, 2),
- 'blender': (2, 5, 3),
- 'location': 'File > Export',
- 'description': 'Export to the MikuMikuDance Model Format (.pmd)',
- 'warning': '', # used for warning icon and text in addons panel
- 'wiki_url': 'http://sourceforge.jp/projects/meshio/wiki/FrontPage',
- '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
-###############################################################################
-import os
-import sys
-
-try:
- # C extension
- from meshio import pmd, englishmap
- print('use meshio C module')
-except ImportError:
- # full python
- from pymeshio import englishmap
- from pymeshio import mmd as pmd
- pmd.IO=pmd.PMDLoader
-
-def isBlender24():
- return sys.version_info[0]<3
-
-if isBlender24():
- # for 2.4
- import Blender
- from Blender import Mathutils
- import bpy
-
- # wrapper
- import bl24 as bl
-
- def setMaterialParams(material, m):
- # diffuse
- material.diffuse.r=m.R
- material.diffuse.g=m.G
- material.diffuse.b=m.B
- material.diffuse.a=m.alpha
- # specular
- material.shinness=0 if m.spec<1e-5 else m.spec*10
- material.specular.r=m.specR
- material.specular.g=m.specG
- material.specular.b=m.specB
- # ambient
- material.ambient.r=m.mirR
- material.ambient.g=m.mirG
- material.ambient.b=m.mirB
- # flag
- material.flag=1 if m.enableSSS else 0
-
- def toCP932(s):
- return s
-
-
-else:
- # for 2.5
- import bpy
- import mathutils
-
- # wrapper
- import bl25 as bl
-
- xrange=range
-
- def setMaterialParams(material, m):
- # diffuse
- material.diffuse.r=m.diffuse_color[0]
- material.diffuse.g=m.diffuse_color[1]
- material.diffuse.b=m.diffuse_color[2]
- material.diffuse.a=m.alpha
- # specular
- material.shinness=0 if m.specular_toon_size<1e-5 else m.specular_hardness*10
- material.specular.r=m.specular_color[0]
- material.specular.g=m.specular_color[1]
- material.specular.b=m.specular_color[2]
- # ambient
- material.ambient.r=m.mirror_color[0]
- material.ambient.g=m.mirror_color[1]
- material.ambient.b=m.mirror_color[2]
- # flag
- material.flag=1 if m.subsurface_scattering.enabled else 0
- # toon
- material.toon_index=7
-
- def toCP932(s):
- return s.encode('cp932')
-
-
-class Node(object):
- __slots__=['o', 'children']
- def __init__(self, o):
- self.o=o
- self.children=[]
-
-
-###############################################################################
-# Blenderのメッシュをワンスキンメッシュ化する
-###############################################################################
-def near(x, y, EPSILON=1e-5):
- d=x-y
- return d>=-EPSILON and d<=EPSILON
-
-
-class VertexAttribute(object):
- __slots__=[
- 'nx', 'ny', 'nz', # normal
- 'u', 'v', # uv
- ]
- def __init__(self, nx, ny, nz, u, v):
- self.nx=nx
- self.ny=ny
- self.nz=nz
- self.u=u
- self.v=v
-
- def __str__(self):
- return "<vkey: %f, %f, %f, %f, %f>" % (
- self.nx, self.ny, self.nz, self.u, self.v)
-
- def __hash__(self):
- return self.nx + self.ny + self.nz + self.u + self.v
-
- def __eq__(self, rhs):
- return self.nx==rhs.nx and self.ny==rhs.ny and self.nz==rhs.nz and self.u==rhs.u and self.v==rhs.v
-
-
-class VertexKey(object):
- __slots__=[
- 'obj_index', 'index',
- ]
-
- def __init__(self, obj_index, index):
- self.obj_index=obj_index
- self.index=index
-
- def __str__(self):
- return "<vkey: %d, %d>" % (self.obj_index, self.index)
-
- def __hash__(self):
- return self.index*100+self.obj_index
-
- def __eq__(self, rhs):
- return self.obj_index==rhs.obj_index and self.index==rhs.index
-
-
-class VertexArray(object):
- """
- 頂点配列
- """
- __slots__=[
- 'indexArrays',
- 'positions',
- 'attributes', # normal and uv
- 'b0', 'b1', 'weight',
- 'vertexMap',
- 'objectMap',
- ]
- def __init__(self):
- # indexArrays split with each material
- self.indexArrays={}
-
- self.positions=[]
- self.attributes=[]
- self.b0=[]
- self.b1=[]
- self.weight=[]
-
- self.vertexMap={}
- self.objectMap={}
-
- def __str__(self):
- return "<VertexArray %d positions, %d indexArrays>" % (
- len(self.positions), len(self.indexArrays))
-
- def zip(self):
- return zip(
- self.positions, self.attributes,
- self.b0, self.b1, self.weight)
-
- def each(self):
- keys=[key for key in self.indexArrays.keys()]
- keys.sort()
- for key in keys:
- yield(key, self.indexArrays[key])
-
- def __addOrGetIndex(self, obj_index, base_index, pos, normal, uv, b0, b1, weight0):
- key=VertexKey(obj_index, base_index)
- attribute=VertexAttribute(
- normal[0], normal[1], normal[2],
- uv[0], uv[1])
- if key in self.vertexMap:
- if attribute in self.vertexMap[key]:
- return self.vertexMap[key][attribute]
- else:
- return self.__addVertex(self.vertexMap[key],
- pos, attribute, b0, b1, weight0)
- else:
- vertexMapKey={}
- self.vertexMap[key]=vertexMapKey
- return self.__addVertex(vertexMapKey,
- pos, attribute, b0, b1, weight0)
-
- def __addVertex(self, vertexMapKey, pos, attribute, b0, b1, weight0):
- index=len(self.positions)
- vertexMapKey[attribute]=index
- # position
- self.positions.append((pos.x, pos.y, pos.z))
- # unique attribute
- self.attributes.append(attribute)
- # shared attribute
- self.b0.append(b0)
- self.b1.append(b1)
- self.weight.append(weight0)
- assert(index<=65535)
- return index
-
- def getMappedIndex(self, obj_name, base_index):
- return self.vertexMap[VertexKey(self.objectMap[obj_name], base_index)]
-
- def addTriangle(self,
- object_name, material,
- base_index0, base_index1, base_index2,
- pos0, pos1, pos2,
- n0, n1, n2,
- uv0, uv1, uv2,
- b0_0, b0_1, b0_2,
- b1_0, b1_1, b1_2,
- weight0, weight1, weight2
- ):
- if object_name in self.objectMap:
- obj_index=self.objectMap[object_name]
- else:
- obj_index=len(self.objectMap)
- self.objectMap[object_name]=obj_index
- index0=self.__addOrGetIndex(obj_index, base_index0, pos0, n0, uv0, b0_0, b1_0, weight0)
- index1=self.__addOrGetIndex(obj_index, base_index1, pos1, n1, uv1, b0_1, b1_1, weight1)
- index2=self.__addOrGetIndex(obj_index, base_index2, pos2, n2, uv2, b0_2, b1_2, weight2)
-
- if not material in self.indexArrays:
- self.indexArrays[material]=[]
- self.indexArrays[material]+=[index0, index1, index2]
-
-
-class Morph(object):
- __slots__=['name', 'type', 'offsets']
- def __init__(self, name, type):
- self.name=name
- self.type=type
- self.offsets=[]
-
- def add(self, index, offset):
- self.offsets.append((index, offset))
-
- def sort(self):
- if isBlender24():
- self.offsets.sort(lambda l, r: l[0]-r[0])
- else:
- self.offsets.sort(key=lambda e: e[0])
-
- def __str__(self):
- return "<Morph %s>" % self.name
-
-class IKSolver(object):
- __slots__=['target', 'effector', 'length', 'iterations', 'weight']
- def __init__(self, target, effector, length, iterations, weight):
- self.target=target
- self.effector=effector
- self.length=length
- self.iterations=iterations
- self.weight=weight
-
-
-class OneSkinMesh(object):
- __slots__=['vertexArray', 'morphList', 'rigidbodies', 'constraints', ]
- def __init__(self):
- self.vertexArray=VertexArray()
- self.morphList=[]
- self.rigidbodies=[]
- self.constraints=[]
-
- def __str__(self):
- return "<OneSkinMesh %s, morph:%d>" % (
- self.vertexArray,
- len(self.morphList))
-
- def addMesh(self, obj):
- if not bl.object.isVisible(obj):
- return
- self.__mesh(obj)
- self.__skin(obj)
- self.__rigidbody(obj)
- self.__constraint(obj)
-
- def __getWeightMap(self, obj, mesh):
- # bone weight
- weightMap={}
- secondWeightMap={}
- def setWeight(i, name, w):
- if w>0:
- if i in weightMap:
- if i in secondWeightMap:
- # 上位2つのweightを採用する
- if w<secondWeightMap[i][1]:
- pass
- elif w<weightMap[i][1]:
- # 2つ目を入れ替え
- secondWeightMap[i]=(name, w)
- else:
- # 1つ目を入れ替え
- weightMap[i]=(name, w)
- else:
- if w>weightMap[i][1]:
- # 多い方をweightMapに
- secondWeightMap[i]=weightMap[i]
- weightMap[i]=(name, w)
- else:
- secondWeightMap[i]=(name, w)
- else:
- weightMap[i]=(name, w)
-
- # ToDo bone weightと関係ないvertex groupを除外する
- if isBlender24():
- for name in bl.object.getVertexGroupNames(obj):
- for i, w in mesh.getVertsFromGroup(name, 1):
- setWeight(i, name, w)
- else:
- for i, v in enumerate(mesh.verts):
- if len(v.groups)>0:
- for g in v.groups:
- setWeight(i, obj.vertex_groups[g.group].name, g.weight)
- else:
- setWeight(i, obj.vertex_groups[0].name, 1)
-
- # 合計値が1になるようにする
- for i in xrange(len(mesh.verts)):
- if i in secondWeightMap:
- secondWeightMap[i]=(secondWeightMap[i][0], 1.0-weightMap[i][1])
- elif i in weightMap:
- weightMap[i]=(weightMap[i][0], 1.0)
- secondWeightMap[i]=("", 0)
- else:
- print("no weight vertex")
- weightMap[i]=("", 0)
- secondWeightMap[i]=("", 0)
-
- return weightMap, secondWeightMap
-
- def __processFaces(self, obj_name, mesh, weightMap, secondWeightMap):
- # 各面の処理
- for i, face in enumerate(mesh.faces):
- faceVertexCount=bl.face.getVertexCount(face)
- material=mesh.materials[bl.face.getMaterialIndex(face)]
- v=[mesh.verts[index] for index in bl.face.getVertices(face)]
- uv=bl.mesh.getFaceUV(
- mesh, i, face, bl.face.getVertexCount(face))
- # flip triangle
- if faceVertexCount==3:
- # triangle
- self.vertexArray.addTriangle(
- obj_name, material.name,
- v[2].index,
- v[1].index,
- v[0].index,
- v[2].co,
- v[1].co,
- v[0].co,
- bl.vertex.getNormal(v[2]),
- bl.vertex.getNormal(v[1]),
- bl.vertex.getNormal(v[0]),
- uv[2],
- uv[1],
- uv[0],
- weightMap[v[2].index][0],
- weightMap[v[1].index][0],
- weightMap[v[0].index][0],
- secondWeightMap[v[2].index][0],
- secondWeightMap[v[1].index][0],
- secondWeightMap[v[0].index][0],
- weightMap[v[2].index][1],
- weightMap[v[1].index][1],
- weightMap[v[0].index][1]
- )
- elif faceVertexCount==4:
- # quadrangle
- self.vertexArray.addTriangle(
- obj_name, material.name,
- v[2].index,
- v[1].index,
- v[0].index,
- v[2].co,
- v[1].co,
- v[0].co,
- bl.vertex.getNormal(v[2]),
- bl.vertex.getNormal(v[1]),
- bl.vertex.getNormal(v[0]),
- uv[2],
- uv[1],
- uv[0],
- weightMap[v[2].index][0],
- weightMap[v[1].index][0],
- weightMap[v[0].index][0],
- secondWeightMap[v[2].index][0],
- secondWeightMap[v[1].index][0],
- secondWeightMap[v[0].index][0],
- weightMap[v[2].index][1],
- weightMap[v[1].index][1],
- weightMap[v[0].index][1]
- )
- self.vertexArray.addTriangle(
- obj_name, material.name,
- v[0].index,
- v[3].index,
- v[2].index,
- v[0].co,
- v[3].co,
- v[2].co,
- bl.vertex.getNormal(v[0]),
- bl.vertex.getNormal(v[3]),
- bl.vertex.getNormal(v[2]),
- uv[0],
- uv[3],
- uv[2],
- weightMap[v[0].index][0],
- weightMap[v[3].index][0],
- weightMap[v[2].index][0],
- secondWeightMap[v[0].index][0],
- secondWeightMap[v[3].index][0],
- secondWeightMap[v[2].index][0],
- weightMap[v[0].index][1],
- weightMap[v[3].index][1],
- weightMap[v[2].index][1]
- )
-
- def __mesh(self, obj):
- if isBlender24():
- pass
- else:
- if RIGID_SHAPE_TYPE in obj:
- return
- if CONSTRAINT_A in obj:
- return
-
- #if not bl.modifier.hasType(obj, 'ARMATURE'):
- # return
-
- bl.message("export: %s" % obj.name)
-
- # メッシュのコピーを生成してオブジェクトの行列を適用する
- copyMesh, copyObj=bl.object.duplicate(obj)
- if len(copyMesh.verts)>0:
- # apply transform
- copyObj.scale=obj.scale
- bpy.ops.object.scale_apply()
- copyObj.rotation_euler=obj.rotation_euler
- bpy.ops.object.rotation_apply()
- copyObj.location=obj.location
- bpy.ops.object.location_apply()
- # apply modifier
- for m in [m for m in copyObj.modifiers]:
- if m.type=='SOLIDFY':
- continue
- elif m.type=='ARMATURE':
- continue
- elif m.type=='MIRROR':
- bpy.ops.object.modifier_apply(modifier=m.name)
- else:
- print(m.type)
-
- weightMap, secondWeightMap=self.__getWeightMap(copyObj, copyMesh)
- self.__processFaces(obj.name, copyMesh, weightMap, secondWeightMap)
- bl.object.delete(copyObj)
-
- def createEmptyBasicSkin(self):
- self.__getOrCreateMorph('base', 0)
-
- def __skin(self, obj):
- if not bl.object.hasShapeKey(obj):
- return
-
- indexRelativeMap={}
- blenderMesh=bl.object.getData(obj)
- baseMorph=None
-
- # shape keys
- vg=bl.object.getVertexGroup(obj, MMD_SHAPE_GROUP_NAME)
-
- # base
- used=set()
- for b in bl.object.getShapeKeys(obj):
- if b.name==BASE_SHAPE_NAME:
- baseMorph=self.__getOrCreateMorph('base', 0)
- basis=b
-
- relativeIndex=0
- for index in vg:
- v=bl.shapekey.getByIndex(b, index)
- pos=[v[0], v[1], v[2]]
-
- indices=self.vertexArray.getMappedIndex(obj.name, index)
- for attribute, i in indices.items():
- if i in used:
- continue
- used.add(i)
-
- baseMorph.add(i, pos)
- indexRelativeMap[i]=relativeIndex
- relativeIndex+=1
-
- break
- assert(basis)
- print(basis.name, len(baseMorph.offsets))
-
- if len(baseMorph.offsets)==0:
- return
-
- # shape keys
- for b in bl.object.getShapeKeys(obj):
- if b.name==BASE_SHAPE_NAME:
- continue
-
- print(b.name)
- morph=self.__getOrCreateMorph(b.name, 4)
- used=set()
- for index, src, dst in zip(
- xrange(len(blenderMesh.verts)),
- bl.shapekey.get(basis),
- bl.shapekey.get(b)):
- offset=[dst[0]-src[0], dst[1]-src[1], dst[2]-src[2]]
- if offset[0]==0 and offset[1]==0 and offset[2]==0:
- continue
- if index in vg:
- indices=self.vertexArray.getMappedIndex(obj.name, index)
- for attribute, i in indices.items():
- if i in used:
- continue
- used.add(i)
- morph.add(indexRelativeMap[i], offset)
- assert(len(morph.offsets)<len(baseMorph.offsets))
-
- # sort skinmap
- original=self.morphList[:]
- def getIndex(morph):
- for i, v in enumerate(englishmap.skinMap):
- if v[0]==morph.name:
- return i
- print(morph)
- return len(englishmap.skinMap)
- if isBlender24():
- self.morphList.sort(lambda l, r: getIndex(l)-getIndex(r))
- else:
- self.morphList.sort(key=getIndex)
-
- def __rigidbody(self, obj):
- if isBlender24():
- return
- if not RIGID_SHAPE_TYPE in obj:
- return
- self.rigidbodies.append(obj)
-
- def __constraint(self, obj):
- if isBlender24():
- return
- if not CONSTRAINT_A in obj:
- return
- self.constraints.append(obj)
-
- def __getOrCreateMorph(self, name, type):
- for m in self.morphList:
- if m.name==name:
- return m
- m=Morph(name, type)
- self.morphList.append(m)
- return m
-
- def getVertexCount(self):
- return len(self.vertexArray.positions)
-
-
-class Bone(object):
- __slots__=['index', 'name', 'ik_index',
- 'pos', 'tail', 'parent_index', 'tail_index', 'type', 'isConnect']
- def __init__(self, name, pos, tail, isConnect):
- self.index=-1
- self.name=name
- self.pos=pos
- self.tail=tail
- self.parent_index=None
- self.tail_index=None
- self.type=0
- self.isConnect=isConnect
- self.ik_index=0
-
- def __eq__(self, rhs):
- return self.index==rhs.index
-
- def __str__(self):
- return "<Bone %s %d>" % (self.name, self.type)
-
-class BoneBuilder(object):
- __slots__=['bones', 'boneMap', 'ik_list', 'bone_groups',]
- def __init__(self):
- self.bones=[]
- self.boneMap={}
- self.ik_list=[]
- self.bone_groups=[]
-
- def getBoneGroup(self, bone):
- for i, g in enumerate(self.bone_groups):
- for b in g[1]:
- if b==bone.name:
- return i+1
- print('no gorup', bone)
- return 0
-
- def build(self, armatureObj):
- if not armatureObj:
- return
-
- bl.message("build skeleton")
- armature=bl.object.getData(armatureObj)
-
- ####################
- # bone group
- ####################
- for g in bl.object.boneGroups(armatureObj):
- self.bone_groups.append((g.name, []))
-
- ####################
- # get bones
- ####################
- for b in armature.bones.values():
- if not b.parent:
- # root bone
- bone=Bone(b.name,
- bl.bone.getHeadLocal(b),
- bl.bone.getTailLocal(b),
- False)
- self.__addBone(bone)
- self.__getBone(bone, b)
-
- for b in armature.bones.values():
- if not b.parent:
- self.__checkConnection(b, None)
-
- ####################
- # get IK
- ####################
- pose = bl.object.getPose(armatureObj)
- for b in pose.bones.values():
- ####################
- # assing bone group
- ####################
- self.__assignBoneGroup(b, b.bone_group)
- for c in b.constraints:
- if bl.constraint.isIKSolver(c):
- ####################
- # IK target
- ####################
- target=self.__boneByName(bl.constraint.ikTarget(c))
- target.type=2
-
- ####################
- # IK effector
- ####################
- # IK 接続先
- link=self.__boneByName(b.name)
- link.type=6
-
- # IK chain
- e=b.parent
- chainLength=bl.constraint.ikChainLen(c)
- for i in range(chainLength):
- # IK影響下
- chainBone=self.__boneByName(e.name)
- chainBone.type=4
- chainBone.ik_index=target.index
- e=e.parent
- self.ik_list.append(
- IKSolver(target, link, chainLength,
- int(bl.constraint.ikItration(c) * 0.1),
- bl.constraint.ikRotationWeight(c)
- ))
-
- ####################
-
- # boneのsort
- self._sortBy()
- self._fix()
- # IKのsort
- def getIndex(ik):
- for i, v in enumerate(englishmap.boneMap):
- if v[0]==ik.target.name:
- return i
- return len(englishmap.boneMap)
- if isBlender24():
- self.ik_list.sort(lambda l, r: getIndex(l)-getIndex(r))
- else:
- self.ik_list.sort(key=getIndex)
-
- def __assignBoneGroup(self, poseBone, boneGroup):
- if boneGroup:
- for g in self.bone_groups:
- if g[0]==boneGroup.name:
- g[1].append(poseBone.name)
-
- def __checkConnection(self, b, p):
- if bl.bone.isConnected(b):
- parent=self.__boneByName(p.name)
- parent.isConnect=True
-
- for c in b.children:
- self.__checkConnection(c, b)
-
- def _sortBy(self):
- """
- boneMap順に並べ替える
- """
- boneMap=englishmap.boneMap
- original=self.bones[:]
- def getIndex(bone):
- for i, k_v in enumerate(boneMap):
- if k_v[0]==bone.name:
- return i
- print(bone)
- return len(boneMap)
-
- if isBlender24():
- self.bones.sort(lambda l, r: getIndex(l)-getIndex(r))
- else:
- self.bones.sort(key=getIndex)
-
- sortMap={}
- for i, b in enumerate(self.bones):
- src=original.index(b)
- sortMap[src]=i
- for b in self.bones:
- b.index=sortMap[b.index]
- if b.parent_index:
- b.parent_index=sortMap[b.parent_index]
- if b.tail_index:
- b.tail_index=sortMap[b.tail_index]
- if b.ik_index>0:
- b.ik_index=sortMap[b.ik_index]
-
- def _fix(self):
- """
- 調整
- """
- for b in self.bones:
- # parent index
- if b.parent_index==None:
- b.parent_index=0xFFFF
- else:
- if b.type==6 or b.type==7:
- # fix tail bone
- parent=self.bones[b.parent_index]
- #print('parnet', parent.name)
- parent.tail_index=b.index
-
- for b in self.bones:
- if b.tail_index==None:
- b.tail_index=0
- elif b.type==9:
- b.tail_index==0
-
- def getIndex(self, bone):
- for i, b in enumerate(self.bones):
- if b==bone:
- return i
- assert(false)
-
- def indexByName(self, name):
- if name=='':
- return 0
- else:
- return self.getIndex(self.__boneByName(name))
-
- def __boneByName(self, name):
- return self.boneMap[name]
-
- def __getBone(self, parent, b):
- if len(b.children)==0:
- parent.type=7
- return
-
- for i, c in enumerate(b.children):
- bone=Bone(c.name,
- bl.bone.getHeadLocal(c),
- bl.bone.getTailLocal(c),
- bl.bone.isConnected(c))
- self.__addBone(bone)
- if parent:
- bone.parent_index=parent.index
- #if i==0:
- if bone.isConnect or (not parent.tail_index and parent.tail==bone.pos):
- parent.tail_index=bone.index
- self.__getBone(bone, c)
-
- def __addBone(self, bone):
- bone.index=len(self.bones)
- self.bones.append(bone)
- self.boneMap[bone.name]=bone
-
-
-class PmdExporter(object):
-
- __slots__=[
- 'armatureObj',
- 'oneSkinMesh',
- 'englishName',
- 'englishComment',
- 'name',
- 'comment',
- 'skeleton',
- ]
- def setup(self):
- self.armatureObj=None
-
- # 木構造を構築する
- object_node_map={}
- for o in bl.object.each():
- object_node_map[o]=Node(o)
- for o in bl.object.each():
- node=object_node_map[o]
- if node.o.parent:
- object_node_map[node.o.parent].children.append(node)
-
- # ルートを得る
- 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.oneSkinMesh=OneSkinMesh()
- self.__createOneSkinMesh(root)
- bl.message(self.oneSkinMesh)
- if len(self.oneSkinMesh.morphList)==0:
- # create emtpy skin
- self.oneSkinMesh.createEmptyBasicSkin()
-
- # skeleton
- self.skeleton=BoneBuilder()
- self.skeleton.build(self.armatureObj)
-
- def __createOneSkinMesh(self, node):
- ############################################################
- # search armature modifier
- ############################################################
- for m in node.o.modifiers:
- if bl.modifier.isType(m, 'ARMATURE'):
- armatureObj=bl.modifier.getArmatureObject(m)
- if not self.armatureObj:
- self.armatureObj=armatureObj
- elif self.armatureObj!=armatureObj:
- print("warning! found multiple armature. ignored.",
- armatureObj.name)
-
- if node.o.type.upper()=='MESH':
- self.oneSkinMesh.addMesh(node.o)
-
- for child in node.children:
- self.__createOneSkinMesh(child)
-
- def write(self, path):
- io=pmd.IO()
- io.setName(toCP932(self.name))
- io.setComment(toCP932(self.comment))
- io.version=1.0
-
- # 頂点
- for pos, attribute, b0, b1, weight in self.oneSkinMesh.vertexArray.zip():
- # convert right-handed z-up to left-handed y-up
- v=io.addVertex()
- v.pos.x=pos[0]
- v.pos.y=pos[2]
- v.pos.z=pos[1]
- v.normal.x=attribute.nx
- v.normal.y=attribute.ny
- v.normal.z=attribute.nz
- v.uv.x=attribute.u
- v.uv.y=1.0-attribute.v # reverse vertical
- v.bone0=self.skeleton.indexByName(b0)
- v.bone1=self.skeleton.indexByName(b1)
- v.weight0=int(100*weight)
- v.edge_flag=0 # edge flag, 0: enable edge, 1: not edge
-
- # 面とマテリアル
- vertexCount=self.oneSkinMesh.getVertexCount()
- for material_name, indices in self.oneSkinMesh.vertexArray.each():
- #print('material:', material_name)
- m=bl.material.get(material_name)
- # マテリアル
- material=io.addMaterial()
- setMaterialParams(material, m)
-
- material.vertex_count=len(indices)
- material.toon_index=0
- textures=[os.path.basename(path)
- for path in bl.material.eachEnalbeTexturePath(m)]
- if len(textures)>0:
- material.setTexture(toCP932('*'.join(textures)))
- else:
- material.setTexture(toCP932(""))
- # 面
- for i in indices:
- assert(i<vertexCount)
- for i in xrange(0, len(indices), 3):
- # reverse triangle
- io.indices.append(indices[i])
- io.indices.append(indices[i+1])
- io.indices.append(indices[i+2])
-
- # bones
- boneNameMap={}
- for i, b in enumerate(self.skeleton.bones):
- bone=io.addBone()
-
- # name
- boneNameMap[b.name]=i
- v=englishmap.getUnicodeBoneName(b.name)
- if not v:
- v=[b.name, b.name]
- assert(v)
- cp932=v[1].encode('cp932')
- assert(len(cp932)<20)
- bone.setName(cp932)
-
- # english name
- bone_english_name=toCP932(b.name)
- assert(len(bone_english_name)<20)
- bone.setEnglishName(bone_english_name)
-
- if len(v)>=3:
- # has type
- if v[2]==5:
- b.ik_index=self.skeleton.indexByName('eyes')
- bone.type=v[2]
- else:
- bone.type=b.type
-
- bone.parent_index=b.parent_index
- bone.tail_index=b.tail_index
- bone.ik_index=b.ik_index
-
- # convert right-handed z-up to left-handed y-up
- bone.pos.x=b.pos[0] if not near(b.pos[0], 0) else 0
- bone.pos.y=b.pos[2] if not near(b.pos[2], 0) else 0
- bone.pos.z=b.pos[1] if not near(b.pos[1], 0) else 0
-
- # IK
- for ik in self.skeleton.ik_list:
- solver=io.addIK()
- solver.index=self.skeleton.getIndex(ik.target)
- solver.target=self.skeleton.getIndex(ik.effector)
- solver.length=ik.length
- b=self.skeleton.bones[ik.effector.parent_index]
- for i in xrange(solver.length):
- solver.children.append(self.skeleton.getIndex(b))
- b=self.skeleton.bones[b.parent_index]
- solver.iterations=ik.iterations
- solver.weight=ik.weight
-
- # 表情
- for i, m in enumerate(self.oneSkinMesh.morphList):
- # morph
- morph=io.addMorph()
-
- v=englishmap.getUnicodeSkinName(m.name)
- if not v:
- v=[m.name, m.name, 0]
- assert(v)
- cp932=v[1].encode('cp932')
- morph.setName(cp932)
- morph.setEnglishName(m.name.encode('cp932'))
- m.type=v[2]
- morph.type=v[2]
- for index, offset in m.offsets:
- # convert right-handed z-up to left-handed y-up
- morph.append(index, offset[0], offset[2], offset[1])
- morph.vertex_count=len(m.offsets)
-
- # 表情枠
- # type==0はbase
- for i, m in enumerate(self.oneSkinMesh.morphList):
- if m.type==3:
- io.face_list.append(i)
- for i, m in enumerate(self.oneSkinMesh.morphList):
- if m.type==2:
- io.face_list.append(i)
- for i, m in enumerate(self.oneSkinMesh.morphList):
- if m.type==1:
- io.face_list.append(i)
- for i, m in enumerate(self.oneSkinMesh.morphList):
- if m.type==4:
- io.face_list.append(i)
-
- # ボーングループ
- for g in self.skeleton.bone_groups:
- boneDisplayName=io.addBoneGroup()
- # name
- name=englishmap.getUnicodeBoneGroupName(g[0])
- if not name:
- name=g[0]
- boneDisplayName.setName(toCP932(name+'\n'))
- # english
- englishName=g[0]
- boneDisplayName.setEnglishName(toCP932(englishName+'\n'))
-
- # ボーングループメンバー
- for i, b in enumerate(self.skeleton.bones):
- if i==0:
- continue
- if b.type in [6, 7]:
- continue
- io.addBoneDisplay(i, self.skeleton.getBoneGroup(b))
-
- #assert(len(io.bones)==len(io.bone_display_list)+1)
-
- # English
- io.setEnglishName(toCP932(self.englishName))
- io.setEnglishComment(toCP932(self.englishComment))
-
- # toon
- toonMeshObject=None
- for o in bl.object.each():
- try:
- if o.name.startswith(TOON_TEXTURE_OBJECT):
- toonMeshObject=o
- except:
- p(o.name)
- break
- if toonMeshObject:
- toonMesh=bl.object.getData(toonMeshObject)
- toonMaterial=bl.mesh.getMaterial(toonMesh, 0)
- for i in range(10):
- t=bl.material.getTexture(toonMaterial, i)
- if t:
- io.getToonTexture(i).setName(toCP932(t.name))
- else:
- io.getToonTexture(i).setName(toCP932("toon%02d.bmp\n" % i))
- else:
- for i in range(10):
- io.getToonTexture(i).setName(toCP932("toon%02d.bmp\n" % i))
-
- # 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)
- rigidBody=io.addRigidBody()
- rigidBody.setName(name.encode('cp932'))
- rigidNameMap[name]=i
- boneIndex=boneNameMap[obj[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.shapeType=pmd.SHAPE_SPHERE
- rigidBody.w=obj.scale[0]
- elif obj[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:
- rigidBody.shapeType=pmd.SHAPE_CAPSULE
- rigidBody.w=obj.scale[0]
- rigidBody.h=obj.scale[2]
-
- # constraint
- for obj in self.oneSkinMesh.constraints:
- constraint=io.addConstraint()
- constraint.setName(obj[CONSTRAINT_NAME].encode('cp932'))
- constraint.rigidA=rigidNameMap[obj[CONSTRAINT_A]]
- constraint.rigidB=rigidNameMap[obj[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]
-
- # 書き込み
- bl.message('write: %s' % path)
- return io.write(path)
-
-
-def __execute(filename):
- active=bl.object.getActive()
- if not active:
- print("abort. no active object.")
- return
- exporter=PmdExporter()
- exporter.setup()
- print(exporter)
- exporter.write(filename)
- bl.object.activate(active)
-
-
-if isBlender24():
- # for 2.4
- def execute_24(filename):
- bl.initialize('pmd_export', bpy.data.scenes.active)
- __execute(filename.decode(bl.INTERNAL_ENCODING))
- bl.finalize()
-
- Blender.Window.FileSelector(
- execute_24,
- 'Export Metasequoia PMD',
- Blender.sys.makename(ext='.pmd'))
-
-else:
- # for 2.5
- def execute_25(filename, scene):
- bl.initialize('pmd_export', scene)
- __execute(filename)
- bl.finalize()
-
- # operator
- class EXPORT_OT_pmd(bpy.types.Operator):
- '''Save a Metasequoia PMD file.'''
- bl_idname = "export_scene.pmd"
- bl_label = 'Export PMD'
-
- # List of operator properties, the attributes will be assigned
- # to the class instance from the operator settings before calling.
- filepath = bpy.props.StringProperty()
- filename = bpy.props.StringProperty()
- directory = bpy.props.StringProperty()
-
- def execute(self, context):
- execute_25(
- self.properties.filepath,
- context.scene
- )
- return 'FINISHED'
-
- def invoke(self, context, event):
- wm=context.window_manager
- try:
- wm.fileselect_add(self)
- except:
- wm.add_fileselect(self)
- return 'RUNNING_MODAL'
-
- # register menu
- def menu_func(self, context):
- default_path=bpy.data.filepath.replace(".blend", ".pmd")
- self.layout.operator(
- EXPORT_OT_pmd.bl_idname,
- text="Miku Miku Dance Model(.pmd)",
- icon='PLUGIN'
- ).filepath=default_path
-
- def register():
- bpy.types.INFO_MT_file_export.append(menu_func)
-
- def unregister():
- bpy.types.INFO_MT_file_export.remove(menu_func)
-
- if __name__ == "__main__":
- register()
-
+++ /dev/null
-#!BPY
-# coding:utf-8
-"""
- Name: 'MikuMikuDance model (.pmd)...'
- Blender: 248
- Group: 'Import'
- Tooltip: 'Import PMD file for MikuMikuDance.'
-"""
-__author__= ["ousttrue"]
-__version__= "2.2"
-__url__=()
-__bpydoc__="""
-pmd Importer
-
-This script imports a pmd into Blender for editing.
-
-0.1 20091126: first implement.
-0.2 20091209: implement IK.
-0.3 20091210: implement morph target.
-0.4 20100305: use english name.
-0.5 20100408: cleanup not used vertices.
-0.6 20100416: fix fornt face. texture load fail safe. add progress.
-0.7 20100506: C extension.
-0.8 20100521: add shape_key group.
-1.0 20100530: add invisilbe bone tail(armature layer 2).
-1.1 20100608: integrate 2.4 and 2.5.
-1.2 20100616: implement rigid body.
-1.3 20100619: fix for various models.
-1.4 20100623: fix constraint name.
-1.5 20100626: refactoring.
-1.6 20100629: sphere map.
-1.7 20100703: implement bone group.
-1.8 20100710: implement toon texture.
-1.9 20100718: keep model name, comment.
-2.0 20100724: update for Blender2.53.
-2.1 20100731: add full python module.
-2.2 20101005: update for Blender2.54.
-2.3 20101228: update for Blender2.55.
-"""
-bl_addon_info = {
- 'category': 'Import/Export',
- 'name': 'Import: MikuMikuDance Model Format (.pmd)',
- 'author': 'ousttrue',
- 'version': (2, 2),
- 'blender': (2, 5, 3),
- 'location': 'File > Import',
- 'description': 'Import from the MikuMikuDance Model Format (.pmd)',
- 'warning': '', # used for warning icon and text in addons panel
- 'wiki_url': 'http://sourceforge.jp/projects/meshio/wiki/FrontPage',
- '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
-###############################################################################
-import os
-import sys
-import math
-
-try:
- # C extension
- from meshio import pmd, englishmap
- print('use meshio C module')
-except ImportError:
- # full python
- from pymeshio import englishmap
- from pymeshio import mmd as pmd
- pmd.IO=pmd.PMDLoader
-
-def isBlender24():
- return sys.version_info[0]<3
-
-if isBlender24():
- # for 2.4
- import Blender
- from Blender import Mathutils
- import bpy
-
- # wrapper
- import bl24 as bl
-
- def createPmdMaterial(m, index):
- material=Blender.Material.New()
- # fresnelが無いw
- material.setDiffuseShader(Blender.Material.Shaders.DIFFUSE_TOON)
- material.setRGBCol([m.diffuse.r, m.diffuse.g, m.diffuse.b])
- material.setAlpha(m.diffuse.a)
- # specular
- material.setSpecShader(Blender.Material.Shaders.SPEC_TOON)
- material.setSpec(m.shinness*0.1)
- material.setSpecCol([m.specular.r, m.specular.g, m.specular.b])
- # ambient
- material.setMirCol([m.ambient.r, m.ambient.g, m.ambient.b])
- # flag
- material.enableSSS=True if m.flag==1 else False
- # name
- material.name="m_%02d" % index
- return material
-
- def poseBoneLimit(n, b):
- if n.endswith("_t"):
- return
- if n.startswith("knee_"):
- b.lockYRot=True
- b.lockZRot=True
- b.limitX=True
- b.limitMin=[0, 0, 0]
- b.limitMax=[180, 0, 0]
- elif n.startswith("ankle_"):
- b.lockYRot=True
-
- def setSphereMap(material, index, blend_type='MULTIPLY'):
- slot=material.textures[index]
- slot.mapto=Blender.Texture.MapTo.NOR
- slot.mapping=Blender.Texture.Mappings.SPHERE
- if blend_type=='MULTIPLY':
- slot.blendmode=Blender.Texture.BlendModes.MULTIPLY
- elif blend_type=='ADD':
- slot.blendmode=Blender.Texture.BlendModes.ADD
-
-else:
- # for 2.5
- import bpy
- import mathutils
-
- # wrapper
- import bl25 as bl
-
- xrange=range
-
- def createPmdMaterial(m, index):
- material = bpy.data.materials.new("Material")
- # diffuse
- material.diffuse_shader='FRESNEL'
- material.diffuse_color=([m.diffuse.r, m.diffuse.g, m.diffuse.b])
- material.alpha=m.diffuse.a
- # specular
- material.specular_shader='TOON'
- material.specular_color=([m.specular.r, m.specular.g, m.specular.b])
- material.specular_toon_size=int(m.shinness)
- # ambient
- material.mirror_color=([m.ambient.r, m.ambient.g, m.ambient.b])
- # flag
- material.subsurface_scattering.use=True if m.flag==1 else False
- # other
- material.name="m_%02d" % index
- material.preview_render_type='FLAT'
- material.use_transparency=True
- return material
-
- def poseBoneLimit(n, b):
- if n.endswith("_t"):
- return
- if n.startswith("knee_"):
- b.lock_ik_y=True
- b.lock_ik_z=True
- b.lock_ik_x=False
- # IK limit
- b.use_ik_limit_x=True
- b.ik_min_x=0
- b.ik_max_x=180
- elif n.startswith("ankle_"):
- #b.ik_dof_y=False
- pass
-
- def setSphereMap(material, index, blend_type='MULTIPLY'):
- slot=material.texture_slots[index]
- slot.texture_coords='NORMAL'
- slot.mapping='SPHERE'
- slot.blend_type=blend_type
-
-
-###############################################################################
-def VtoV(v):
- return bl.createVector(v.x, v.y, v.z)
-
-
-def convert_coord(pos):
- """
- Left handed y-up to Right handed z-up
- """
- return (pos.x, pos.z, pos.y)
-
-
-def to_radian(degree):
- return math.pi * degree / 180
-
-
-def get_bone_name(l, index):
- if index==0xFFFF:
- return l.bones[0].getName()
-
- if index < len(l.bones):
- name=englishmap.getEnglishBoneName(l.bones[index].getName())
- if name:
- return name
- return l.bones[index].getName()
- print('invalid bone index', index)
- return l.bones[0].getName()
-
-
-def get_group_name(g):
- group_name=englishmap.getEnglishBoneGroupName(g.getName().strip())
- if not group_name:
- group_name=g.getName().strip()
- return group_name
-
-
-def __importToonTextures(io, tex_dir):
- mesh, meshObject=bl.mesh.create(TOON_TEXTURE_OBJECT)
- material=bl.material.create(TOON_TEXTURE_OBJECT)
- bl.mesh.addMaterial(mesh, material)
- for i in range(10):
- t=io.getToonTexture(i)
- path=os.path.join(tex_dir, t.getName())
- texture, image=bl.texture.create(path)
- bl.material.addTexture(material, texture, False)
- return meshObject, material
-
-
-def __importShape(obj, l, vertex_map):
- if len(l.morph_list)==0:
- return
-
- # set shape_key pin
- bl.object.pinShape(obj, True)
-
- # find base
- base=None
- for s in l.morph_list:
- if s.type==0:
- base=s
-
- # create vertex group
- bl.object.addVertexGroup(obj, 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)
- if not hasShape:
- return
- assert(base)
-
- # create base key
- baseShapeBlock=bl.object.addShapeKey(obj, BASE_SHAPE_NAME)
- # mesh
- mesh=bl.object.getData(obj)
- mesh.update()
-
- # each skin
- for s in l.morph_list:
- if s.type==0:
- continue
-
- # name
- name=englishmap.getEnglishSkinName(s.getName())
- if not name:
- name=s.getName()
-
- if isBlender24():
- # 24
- for index, offset in zip(s.indices, s.pos_list):
- try:
- vertex_index=vertex_map[base.indices[index]]
- v=mesh.vertices[vertex_index].co
- offset=convert_coord(offset)
- v[0]+=offset[0]
- v[1]+=offset[1]
- v[2]+=offset[2]
- except IndexError as msg:
- print(msg)
- print(index, len(base.indices), len(vertex_map))
- print(len(mesh.vertices))
- print(base.indices[index])
- print(vertex_index)
- break
- except KeyError:
- #print 'this mesh not has shape vertices'
- break
-
- # create shapekey block
- new_shape_key=bl.object.addShapeKey(obj, name)
-
- # copy vertex to shape key
- mesh.update()
-
- # restore
- for mv, v in zip(mesh.vertices, baseShapeBlock.getData()):
- mv.co[0] = v[0]
- mv.co[1] = v[1]
- mv.co[2] = v[2]
- mesh.update()
-
- else:
- # 25
- new_shape_key=bl.object.addShapeKey(obj, name)
-
- for index, offset in zip(s.indices, s.pos_list):
- try:
- vertex_index=vertex_map[base.indices[index]]
- bl.shapekey.assign(new_shape_key, vertex_index,
- mesh.vertices[vertex_index].co+
- bl.createVector(*convert_coord(offset)))
- except IndexError as msg:
- print(msg)
- print(index, len(base.indices), len(vertex_map))
- print(len(mesh.vertices))
- print(base.indices[index])
- print(vertex_index)
- break
- except KeyError:
- #print 'this mesh not has shape vertices'
- break
-
- # select base shape
- bl.object.setActivateShapeKey(obj, 0)
-
-
-def __build(armature, b, p, parent):
- name=englishmap.getEnglishBoneName(b.getName())
- if not name:
- name=b.getName()
-
- bone=bl.armature.createBone(armature, name)
-
- if parent and (b.tail_index==0 or b.type==6 or b.type==7 or b.type==9):
- # 先端ボーン
- bone.head = bl.createVector(*convert_coord(b.pos))
- bone.tail=bone.head+bl.createVector(0, 1, 0)
- bone.parent=parent
- if bone.name=="center_t":
- # センターボーンは(0, 1, 0)の方向を向いていないと具合が悪い
- parent.tail=parent.head+bl.createVector(0, 1, 0)
- bone.head=parent.tail
- bone.tail=bone.head+bl.createVector(0, 1, 0)
- else:
- if parent.tail==bone.head:
- pass
- else:
- print('diffurence with parent.tail and head', name)
-
- if b.type!=9:
- bl.bone.setConnected(bone)
- # armature layer 2
- bl.bone.setLayerMask(bone, [0, 1])
- else:
- # 通常ボーン
- bone.head = bl.createVector(*convert_coord(b.pos))
- bone.tail = bl.createVector(*convert_coord(b.tail))
- if parent:
- bone.parent=parent
- if parent.tail==bone.head:
- bl.bone.setConnected(bone)
-
- if bone.head==bone.tail:
- bone.tail=bone.head+bl.createVector(0, 1, 0)
-
- for c in b.children:
- __build(armature, c, b, bone)
-
-
-def __importArmature(l):
- armature, armature_object=bl.armature.create()
-
- # build bone
- bl.armature.makeEditable(armature_object)
- for b in l.bones:
- if not b.parent:
- __build(armature, b, None, None)
- bl.armature.update(armature)
- bl.enterObjectMode()
-
- # IK constraint
- pose = bl.object.getPose(armature_object)
- for ik in l.ik_list:
- target=l.bones[ik.target]
- name = englishmap.getEnglishBoneName(target.getName())
- if not name:
- name=target.getName()
- p_bone = pose.bones[name]
- if not p_bone:
- print('not found', name)
- continue
- if len(ik.children) >= 16:
- print('over MAX_CHAINLEN', ik, len(ik.children))
- continue
- effector_name=englishmap.getEnglishBoneName(
- l.bones[ik.index].getName())
- if not effector_name:
- effector_name=l.bones[ik.index].getName()
-
- constraint=bl.armature.createIkConstraint(armature_object,
- p_bone, effector_name, ik)
-
- bl.armature.makeEditable(armature_object)
- bl.armature.update(armature)
- bl.enterObjectMode()
-
- if isBlender24():
- pass
- else:
- # create bone group
- for i, g in enumerate(l.bone_group_list):
- name=get_group_name(g)
- bl.object.createBoneGroup(armature_object, name, "THEME%02d" % (i+1))
-
- # assign bone to group
- for b_index, g_index in l.bone_display_list:
- # bone
- b=l.bones[b_index]
- bone_name=englishmap.getEnglishBoneName(b.getName())
- if not bone_name:
- bone_name=b.getName()
- # group
- g=l.bone_group_list[g_index-1]
- group_name=get_group_name(g)
-
- # assign
- pose.bones[bone_name].bone_group=pose.bone_groups[group_name]
-
- bl.enterObjectMode()
-
- return armature_object
-
-
-def __import16MaerialAndMesh(meshObject, l,
- material_order, face_map, tex_dir, toon_material):
-
- mesh=bl.object.getData(meshObject)
- ############################################################
- # material
- ############################################################
- bl.progress_print('create materials')
- mesh_material_map={}
- textureMap={}
- imageMap={}
- index=0
-
- for material_index in material_order:
- try:
- m=l.materials[material_index]
- mesh_material_map[material_index]=index
- except KeyError:
- break
-
- material=createPmdMaterial(m, material_index)
-
- # main texture
- texture_name=m.getTexture()
- if texture_name!='':
- for i, t in enumerate(texture_name.split('*')):
- if t in textureMap:
- texture=textureMap[t]
- else:
- path=os.path.join(tex_dir, t)
- texture, image=bl.texture.create(path)
- textureMap[texture_name]=texture
- imageMap[material_index]=image
- texture_index=bl.material.addTexture(material, texture)
- if t.endswith('sph'):
- # sphere map
- setSphereMap(material, texture_index)
- elif t.endswith('spa'):
- # sphere map
- setSphereMap(material, texture_index, 'ADD')
-
- # toon texture
- toon_index=bl.material.addTexture(
- material,
- bl.material.getTexture(
- toon_material,
- 0 if m.toon_index==0xFF else m.toon_index
- ),
- False)
-
- bl.mesh.addMaterial(mesh, material)
-
- index+=1
-
- ############################################################
- # vertex
- ############################################################
- bl.progress_print('create vertices')
- # create vertices
- vertices=[]
- for v in l.each_vertex():
- vertices.append(convert_coord(v.pos))
-
- ############################################################
- # face
- ############################################################
- bl.progress_print('create faces')
- # create faces
- mesh_face_indices=[]
- mesh_face_materials=[]
- used_vertices=set()
-
- for material_index in material_order:
- face_offset=face_map[material_index]
- m=l.materials[material_index]
- material_faces=l.indices[face_offset:face_offset+m.vertex_count]
-
- def degenerate(i0, i1, i2):
- """
- 縮退しているか?
- """
- return i0==i1 or i1==i2 or i2==i0
-
- for j in xrange(0, len(material_faces), 3):
- i0=material_faces[j]
- i1=material_faces[j+1]
- i2=material_faces[j+2]
- # flip
- triangle=[i2, i1, i0]
- if degenerate(*triangle):
- continue
- mesh_face_indices.append(triangle[0:3])
- mesh_face_materials.append(material_index)
- used_vertices.add(i0)
- used_vertices.add(i1)
- used_vertices.add(i2)
-
- ############################################################
- # create vertices & faces
- ############################################################
- bl.mesh.addGeometry(mesh, vertices, mesh_face_indices)
-
- ############################################################
- # vertex bone weight
- ############################################################
- # create vertex group
- vertex_groups={}
- for v in l.each_vertex():
- vertex_groups[v.bone0]=True
- vertex_groups[v.bone1]=True
- for i in vertex_groups.keys():
- bl.object.addVertexGroup(meshObject, get_bone_name(l, i))
-
- # vertex params
- bl.mesh.useVertexUV(mesh)
- for i, v, mvert in zip(xrange(len(l.vertices)),
- l.each_vertex(), mesh.vertices):
- # normal, uv
- bl.vertex.setNormal(mvert, convert_coord(v.normal))
- # bone weight
- w1=float(v.weight0)/100.0
- w2=1.0-w1
- bl.object.assignVertexGroup(meshObject, get_bone_name(l, v.bone0),
- i, w1)
- bl.object.assignVertexGroup(meshObject, get_bone_name(l, v.bone1),
- i, w2)
-
- ############################################################
- # face params
- ############################################################
- used_map={}
- bl.mesh.addUV(mesh)
- for i, (face, material_index) in enumerate(
- zip(mesh.faces, mesh_face_materials)):
- try:
- index=mesh_material_map[material_index]
- except KeyError as message:
- print(message, mesh_material_map, m)
- assert(False)
- bl.face.setMaterial(face, index)
- material=mesh.materials[index]
- used_map[index]=True
- if bl.material.hasTexture(material):
- uv_array=[l.getUV(i) for i in bl.face.getIndices(face)]
- bl.mesh.setFaceUV(mesh, i, face,
- # fix uv
- [(uv.x, 1.0-uv.y) for uv in uv_array],
- imageMap.get(index, None))
-
- # set smooth
- bl.face.setSmooth(face, True)
-
- mesh.update()
-
- ############################################################
- # clean up not used vertices
- ############################################################
- bl.progress_print('clean up vertices not used')
- remove_vertices=[]
- vertex_map={}
- for i, v in enumerate(l.each_vertex()):
- if i in used_vertices:
- vertex_map[i]=len(vertex_map)
- else:
- remove_vertices.append(i)
-
- bl.mesh.vertsDelete(mesh, remove_vertices)
-
- bl.progress_print('%s created' % mesh.name)
- return vertex_map
-
-
-def __importMaterialAndMesh(io, tex_dir, toon_material):
- """
- @param l[in] mmd.PMDLoader
- @param filename[in]
- """
- ############################################################
- # shpaeキーで使われるマテリアル優先的に前に並べる
- ############################################################
- # shapeキーで使われる頂点インデックスを集める
- shape_key_used_vertices=set()
- if len(io.morph_list)>0:
- # base
- base=None
- for s in io.morph_list:
- if s.type!=0:
- continue
- base=s
- break
- assert(base)
-
- for index in base.indices:
- shape_key_used_vertices.add(index)
-
- # マテリアルに含まれる頂点がshape_keyに含まれるか否か?
- def isMaterialUsedInShape(offset, m):
- for i in xrange(offset, offset+m.vertex_count):
- if io.indices[i] in shape_key_used_vertices:
- return True
-
- material_with_shape=set()
-
- # 各マテリアルの開始頂点インデックスを記録する
- face_map={}
- face_count=0
- for i, m in enumerate(io.materials):
- face_map[i]=face_count
- if isMaterialUsedInShape(face_count, m):
- material_with_shape.add(i)
- face_count+=m.vertex_count
-
- # shapeキーで使われる頂点のあるマテリアル
- material_with_shape=list(material_with_shape)
- material_with_shape.sort()
-
- # shapeキーに使われていないマテリアル
- material_without_shape=[]
- for i in range(len(io.materials)):
- if not i in material_with_shape:
- material_without_shape.append(i)
-
- # メッシュの生成
- def __splitList(l, length):
- for i in range(0, len(l), length):
- yield l[i:i+length]
-
- def __importMeshAndShape(material16, name):
- mesh, meshObject=bl.mesh.create(name)
-
- # activate object
- bl.object.deselectAll()
- bl.object.activate(meshObject)
-
- # shapeキーで使われる順に並べなおしたマテリアル16個分の
- # メッシュを作成する
- vertex_map=__import16MaerialAndMesh(
- meshObject, io, material16, face_map, tex_dir, toon_material)
-
- # crete shape key
- __importShape(meshObject, io, vertex_map)
-
- mesh.update()
- return meshObject
-
- mesh_objects=[__importMeshAndShape(material16, 'with_shape')
- for material16 in __splitList(material_with_shape, 16)]
-
- mesh_objects+=[__importMeshAndShape(material16, 'mesh')
- for material16 in __splitList(material_without_shape, 16)]
-
- return mesh_objects
-
-
-def __importConstraints(io):
- if isBlender24():
- return
- print("create constraint")
- container=bl.object.createEmpty('Constraints')
- layer=[
- True, False, False, False, False, False, False, False, False, False,
- False, False, False, False, False, False, False, False, False, False,
- ]
- material=bl.material.create('constraint')
- material.diffuse_color=(1, 0, 0)
- constraintMeshes=[]
- for i, c in enumerate(io.constraints):
- bpy.ops.mesh.primitive_uv_sphere_add(
- segments=8,
- rings=4,
- size=0.1,
- location=(c.pos.x, c.pos.z, c.pos.y),
- layer=layer
- )
- meshObject=bl.object.getActive()
- constraintMeshes.append(meshObject)
- mesh=bl.object.getData(meshObject)
- bl.mesh.addMaterial(mesh, material)
- meshObject.name='c_%d' % i
- #meshObject.draw_transparent=True
- #meshObject.draw_wire=True
- meshObject.max_draw_type='SOLID'
- rot=c.rot
- meshObject.rotation_euler=(-rot.x, -rot.z, -rot.y)
-
- meshObject[CONSTRAINT_NAME]=c.getName()
- meshObject[CONSTRAINT_A]=io.rigidbodies[c.rigidA].getName()
- meshObject[CONSTRAINT_B]=io.rigidbodies[c.rigidB].getName()
- 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)
-
- for meshObject in reversed(constraintMeshes):
- bl.object.makeParent(container, meshObject)
-
- return container
-
-
-def __importRigidBodies(io):
- if isBlender24():
- return
- print("create rigid bodies")
-
- container=bl.object.createEmpty('RigidBodies')
- layer=[
- True, False, False, False, False, False, False, False, False, False,
- False, False, False, False, False, False, False, False, False, False,
- ]
- material=bl.material.create('rigidBody')
- rigidMeshes=[]
- for i, rigid in enumerate(io.rigidbodies):
- if rigid.boneIndex==0xFFFF:
- # no reference bone
- bone=io.bones[0]
- else:
- bone=io.bones[rigid.boneIndex]
- pos=bone.pos+rigid.position
-
- if rigid.shapeType==pmd.SHAPE_SPHERE:
- bpy.ops.mesh.primitive_ico_sphere_add(
- location=(pos.x, pos.z, pos.y),
- layer=layer
- )
- bpy.ops.transform.resize(
- value=(rigid.w, rigid.w, rigid.w))
- elif rigid.shapeType==pmd.SHAPE_BOX:
- bpy.ops.mesh.primitive_cube_add(
- location=(pos.x, pos.z, pos.y),
- layer=layer
- )
- bpy.ops.transform.resize(
- value=(rigid.w, rigid.d, rigid.h))
- elif rigid.shapeType==pmd.SHAPE_CAPSULE:
- bpy.ops.mesh.primitive_tube_add(
- location=(pos.x, pos.z, pos.y),
- layer=layer
- )
- bpy.ops.transform.resize(
- value=(rigid.w, rigid.w, rigid.h))
- else:
- assert(False)
-
- meshObject=bl.object.getActive()
- mesh=bl.object.getData(meshObject)
- rigidMeshes.append(meshObject)
- bl.mesh.addMaterial(mesh, material)
- meshObject.name='r_%d' % i
- meshObject[RIGID_NAME]=rigid.getName()
- #meshObject.draw_transparent=True
- #meshObject.draw_wire=True
- meshObject.max_draw_type='WIRE'
- rot=rigid.rotation
- meshObject.rotation_euler=(-rot.x, -rot.z, -rot.y)
-
- # custom properties
- meshObject[RIGID_SHAPE_TYPE]=rigid.shapeType
- meshObject[RIGID_PROCESS_TYPE]=rigid.processType
-
- bone_name = englishmap.getEnglishBoneName(bone.getName())
- if not bone_name:
- bone_name=bone.getName()
- meshObject[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
-
- for meshObject in reversed(rigidMeshes):
- bl.object.makeParent(container, meshObject)
-
- return container
-
-
-def _execute(filename):
- """
- load pmd file to context.
- """
-
- # load pmd
- bl.progress_set('load %s' % filename, 0.0)
-
- io=pmd.IO()
- if not io.read(filename):
- bl.message("fail to load %s" % filename)
- return
- bl.progress_set('loaded', 0.1)
-
- # create root object
- model_name=io.getEnglishName()
- if len(model_name)==0:
- model_name=io.getName()
- root=bl.object.createEmpty(model_name)
- root[MMD_MB_NAME]=io.getName()
- root[MMD_MB_COMMENT]=io.getComment()
- root[MMD_COMMENT]=io.getEnglishComment()
-
- # toon textures
- tex_dir=os.path.dirname(filename)
- toonTextures, toonMaterial=__importToonTextures(io, tex_dir)
- bl.object.makeParent(root, toonTextures)
-
- # import mesh
- mesh_objects=__importMaterialAndMesh(io, tex_dir, toonMaterial)
- for o in mesh_objects:
- bl.object.makeParent(root, o)
-
- # import armature
- armature_object=__importArmature(io)
- if armature_object:
- bl.object.makeParent(root, armature_object)
- armature = bl.object.getData(armature_object)
-
- # add armature modifier
- for o in mesh_objects:
- bl.modifier.addArmature(o, armature_object)
-
- # Limitation
- for n, b in bl.object.getPose(armature_object).bones.items():
- poseBoneLimit(n, b)
-
- # import rigid bodies
- rigidBodies=__importRigidBodies(io)
- if rigidBodies:
- bl.object.makeParent(root, rigidBodies)
-
- # import constraints
- constraints=__importConstraints(io)
- if constraints:
- bl.object.makeParent(root, constraints)
-
- bl.object.activate(root)
-
-
-if isBlender24():
- # for 2.4
- def execute_24(filename):
- bl.initialize('pmd_import', bpy.data.scenes.active)
- _execute(filename.decode(bl.INTERNAL_ENCODING))
- bl.finalize()
-
- Blender.Window.FileSelector(
- execute_24,
- 'Import PMD file',
- Blender.sys.makename(ext='.pmd'))
-
-else:
- # import operator
- class IMPORT_OT_pmd(bpy.types.Operator):
- bl_idname = "import_scene.pmd"
- bl_label = 'Import PMD'
-
- # List of operator properties, the attributes will be assigned
- # to the class instance from the operator settings before calling.
- filepath = bpy.props.StringProperty()
- filename = bpy.props.StringProperty()
- directory = bpy.props.StringProperty()
-
- def execute(self, context):
- bl.initialize('pmd_import', context.scene)
- _execute(self.properties.filepath)
- bl.finalize()
- return 'FINISHED'
-
- def invoke(self, context, event):
- wm = context.window_manager
- try:
- wm.fileselect_add(self)
- except:
- wm.add_fileselect(self)
- return 'RUNNING_MODAL'
-
- # register menu
- def menu_func(self, context):
- self.layout.operator(IMPORT_OT_pmd.bl_idname,
- text="MikuMikuDance model (.pmd)",
- icon='PLUGIN'
- )
-
- def register():
- bpy.types.INFO_MT_file_import.append(menu_func)
-
- def unregister():
- bpy.types.INFO_MT_file_import.remove(menu_func)
-
- if __name__=="__main__":
- register()
-
+++ /dev/null
-#!/usr/bin/env python
-# coding: utf8
-"""
-日本語名との変換マップ
-"""
-import sys
-
-"""
-ボーン名変換
-"""
-boneMap=[
-("center", "センター", 1),
-("upper body", "上半身"),
-("neck", "首"),
-("head", "頭"),
-("eye_L", "左目", 5),
-("eye_R", "右目", 5),
-("necktie1", "ネクタイ1"),
-("necktie2", "ネクタイ2"),
-("necktie3", "ネクタイ3"),
-("lower body", "下半身"),
-("waist accessory", "腰飾り"),
-("hair1_L", "左髪1"),
-("hair2_L", "左髪2"),
-("hair3_L", "左髪3"),
-("hair4_L", "左髪4"),
-("hair5_L", "左髪5"),
-("hair6_L", "左髪6"),
-("shoulder_L", "左肩"),
-("arm_L", "左腕"),
-("arm twist_L", "左腕捩", 8),
-("elbow_L", "左ひじ"),
-("wrist twist_L", "左手捩", 8),
-("wrist_L", "左手首"),
-("sleeve_L", "左袖", 1),
-("thumb1_L", "左親指1"),
-("thumb2_L", "左親指2"),
-("fore1_L", "左人指1"),
-("fore2_L", "左人指2"),
-("fore3_L", "左人指3"),
-("middle1_L", "左中指1"),
-("middle2_L", "左中指2"),
-("middle3_L", "左中指3"),
-("third1_L", "左薬指1"),
-("third2_L", "左薬指2"),
-("third3_L", "左薬指3"),
-("little1_L", "左小指1"),
-("little2_L", "左小指2"),
-("little3_L", "左小指3"),
-("front skirt_L", "左スカート前"),
-("back skirt_L", "左スカート後"),
-("leg_L", "左足"),
-("knee_L", "左ひざ"),
-("ankle_L", "左足首"),
-("hair1_R", "右髪1"),
-("hair2_R", "右髪2"),
-("hair3_R", "右髪3"),
-("hair4_R", "右髪4"),
-("hair5_R", "右髪5"),
-("hair6_R", "右髪6"),
-("shoulder_R", "右肩"),
-("arm_R", "右腕"),
-("arm twist_R", "右腕捩", 8),
-("elbow_R", "右ひじ"),
-("wrist twist_R", "右手捩", 8),
-("wrist_R", "右手首"),
-("sleeve_R", "右袖", 1),
-("thumb1_R", "右親指1"),
-("thumb2_R", "右親指2"),
-("fore1_R", "右人指1"),
-("fore2_R", "右人指2"),
-("fore3_R", "右人指3"),
-("middle1_R", "右中指1"),
-("middle2_R", "右中指2"),
-("middle3_R", "右中指3"),
-("third1_R", "右薬指1"),
-("third2_R", "右薬指2"),
-("third3_R", "右薬指3"),
-("little1_R", "右小指1"),
-("little2_R", "右小指2"),
-("little3_R", "右小指3"),
-("front skirt_R", "右スカート前"),
-("back skirt_R", "右スカート後"),
-("leg_R", "右足"),
-("knee_R", "右ひざ"),
-("ankle_R", "右足首"),
-("eyes", "両目"),
-("front hair1", "前髪1"),
-("front hair2", "前髪2"),
-("front hair3", "前髪3"),
-("eyelight_L", "左目光"),
-("eyelight_R", "右目光"),
-("necktie3_t", "ネクタイ4"),
-("hair6_L_t", "左髪7"),
-("hair6_R_t", "右髪7"),
-("ankle_L_t", "左つま先"),
-("ankle_R_t", "右つま先"),
-("necktie IK", "ネクタイIK"),
-("hair IK_L", "左髪IK"),
-("hair IK_R", "右髪IK"),
-("leg IK_L", "左足IK"),
-("leg IK_R", "右足IK"),
-("toe IK_L", "左つま先IK"),
-("toe IK_R", "右つま先IK"),
-
-("lower body_t", "下半身先"),
-("head_t", "頭先"),
-("eye_L_t", "左目先"),
-("eye_R_t", "右目先"),
-("waist accessory_t", "腰飾り先"),
-
-("sleeve_L_t", "左袖先"),
-("wrist_L_t", "左手先"),
-("thumb2_L_t", "左親指先"),
-("fore3_L_t", "左人差指先"),
-("middle3_L_t", "左中指先"),
-("third3_L_t", "左薬指先"),
-("little3_L_t", "左小指先"),
-("front skirt_L_t", "左スカート前先"),
-("back skirt_L_t", "左スカート後先"),
-
-("sleeve_R_t", "右袖先"),
-("wrist_R_t", "右手先"),
-("thumb2_R_t", "右親指先"),
-("fore3_R_t", "右人差指先"),
-("middle3_R_t", "右中指先"),
-("third3_R_t", "右薬指先"),
-("little3_R_t", "右小指先"),
-("front skirt_R_t", "右スカート前先"),
-("back skirt_R_t", "右スカート後先"),
-
-("center_t", "センター先"),
-("eyes_t", "両目先"),
-("necktie IK_t", "ネクタイIK先"),
-("hair IK_L_t", "左髪IK先"),
-("hair IK_R_t", "右髪IK先"),
-("leg IK_L_t", "左足IK先"),
-("leg IK_R_t", "右足IK先"),
-("toe IK_L_t", "左つま先IK先"),
-("toe IK_R_t", "右つま先IK先"),
-("front hair1_t", "前髪1先"),
-("front hair2_t", "前髪2先"),
-("front hair3_t", "前髪3先"),
-("eyelight_L_t", "左目光先"),
-("eyelight_R_t", "右目光先"),
-("arm twist_L_t", "左腕捩先"),
-("wrist twist_L_t", "左手捩先"),
-("arm twist_R_t", "右腕捩先"),
-("wrist twist_R_t", "右手捩先"),
-("arm twist1_L", "左腕捩1", 9),
-("arm twist2_L", "左腕捩2", 9),
-("arm twist3_L", "左腕捩3", 9),
-("arm twist1_R", "右腕捩1", 9),
-("arm twist2_R", "右腕捩2", 9),
-("arm twist3_R", "右腕捩3", 9),
-#
-("arm twist1_L_t", "左腕捩1先"),
-("arm twist2_L_t", "左腕捩2先"),
-("arm twist3_L_t", "左腕捩3先"),
-("arm twist1_R_t", "右腕捩1先"),
-("arm twist2_R_t", "右腕捩2先"),
-("arm twist3_R_t", "右腕捩3先"),
-
-# 追加ボーン
-("root", "全ての親"),
-("root_t", "全ての親先"),
-("group", "グループ"),
-("group_t", "グループ先"),
-("front_shirt_L", "左シャツ前"),
-("front_shirt_R", "右シャツ前"),
-("back_shirt_L", "左シャツ後"),
-("back_shirt_R", "右シャツ後"),
-]
-def getEnglishBoneName(name):
- for v in boneMap:
- if v[1]==name:
- return v[0]
-
-def getIndexByEnglish(name):
- for i, v in enumerate(boneMap):
- if v[0]==name:
- return i
-
-def getUnicodeBoneName(name):
- for v in boneMap:
- if v[0]==name:
- return v
-
-"""
-モーフ名変換
-"""
-skinMap=[
-("base", "base", 0),
-("serious", "真面目", 1),
-("sadness", "困る", 1),
-("cheerful", "にこり", 1),
-("anger", "怒り", 1),
-("go up", "上", 1),
-("go down", "下", 1),
-("blink", "まばたき", 2),
-("smile", "笑い", 2),
-("wink", "ウィンク", 2),
-("wink2", "ウィンク2", 2),
-("wink_R", "ウィンク右", 2),
-("wink2_R", "ウィンク2右", 2),
-("close><", "はぅ", 2),
-("calm", "なごみ", 2),
-("surprise", "びっくり", 2),
-("doubt", "じと目", 2),
-("confuse", "なぬ!", 2),
-("pupil", "瞳小", 4),
-("a", "あ", 3),
-("i", "い", 3),
-("u", "う", 3),
-("o", "お", 3),
-("triangle", "▲", 3),
-("regret", "∧", 3),
-("omega", "ω", 3),
-("omegabox", "ω□", 3),
-("fool", "はんっ!", 3),
-("tongue", "ぺろっ", 4),
-("e-", "えー", 3),
-("grin", "にやり", 3),
-]
-def getEnglishSkinName(name):
- for v in skinMap:
- if v[1]==name:
- return v[0]
-
-def getUnicodeSkinName(name):
- for v in skinMap:
- if v[0]==name:
- return v
-
-"""
-ボーングループ名変換
-"""
-boneGroupMap=[
- ("IK", "IK"),
- ("Body[u]", "体(上)"),
- ("Hair", "髪"),
- ("Arms", "腕"),
- ("Fingers", "指"),
- ("Body[l]", "体(下)"),
- ("Legs", "足"),
- ]
-def getEnglishBoneGroupName(name):
- for v in boneGroupMap:
- if v[1]==name:
- return v[0]
-
-def getUnicodeBoneGroupName(name):
- for v in boneGroupMap:
- if v[0]==name:
- return v[1]
-
-
-###############################################################################
-# blender2.4 str to unicode
-###############################################################################
-if sys.version_info[0]<3:
- print('convert boneMap and skinMap to unicode...')
- # python2.x
- # unicodeに変換
- for i, l in enumerate(boneMap):
- replace=[]
- for j, m in enumerate(l):
- if j==1:
- replace.append(m.decode('utf-8'))
- else:
- replace.append(m)
- boneMap[i]=replace
-
- for i, l in enumerate(skinMap):
- replace=[]
- for j, m in enumerate(l):
- if j==1:
- replace.append(m.decode('utf-8'))
- else:
- replace.append(m)
- skinMap[i]=replace
- print('done')
-
+++ /dev/null
-%module mqo
-%{
-#include <mqo.h>
-using namespace meshio;
-using namespace mqo;
-%}
-%include "std_vector.i"
-%include "std_string.i"
-%include "std_wstring.i"
-%include "../include/mqo.h"
-%include "../include/la.h"
-%include "../include/color.h"
-
-%template(MaterialVector) std::vector<meshio::mqo::Material>;
-%template(ObjectVector) std::vector<meshio::mqo::Object>;
-%template(Vector3Vector) std::vector<meshio::mqo::Vector3>;
-%template(FaceVector) std::vector<meshio::mqo::Face>;
-
+++ /dev/null
-%module pmd
-
-///////////////////////////////////////////////////////////////////////////////
-// bytearray typemap
-///////////////////////////////////////////////////////////////////////////////
-%include <pybuffer.i>
-%pybuffer_string(const char *src);
-
-%{
-#include <pmd.h>
-using namespace meshio;
-using namespace pmd;
-%}
-%include "std_vector.i"
-%include "std_wstring.i"
-%include "std_string.i"
-%include "std_pair.i"
-%include "../include/color.h"
-%include "../include/la.h"
-%include "../include/pmd.h"
-
-%template(VertexVector) std::vector<meshio::pmd::Vertex>;
-%template(MaterialVector) std::vector<meshio::pmd::Material*>;
-%template(BoneVector) std::vector<meshio::pmd::Bone>;
-%template(IKVector) std::vector<meshio::pmd::IK>;
-%template(MorphVector) std::vector<meshio::pmd::Morph>;
-%template(RigidBodyVector) std::vector<meshio::pmd::RigidBody>;
-%template(ConstraintVector) std::vector<meshio::pmd::Constraint>;
-%template(UintVector) std::vector<unsigned int>;
-%template(UshortVector) std::vector<unsigned short>;
-%template(Vector3Vector) std::vector<meshio::pmd::Vector3>;
-%template(PBoneVector) std::vector<meshio::pmd::Bone*>;
-%template(BoneGroupVector) std::vector<meshio::pmd::BoneGroup>;
-%template(DisplayPair) std::pair<unsigned short, unsigned char>;
-%template(BoneDisplayVector) std::vector<std::pair<unsigned short, unsigned char> >;
-
-///////////////////////////////////////////////////////////////////////////////
-// meshio::pmd::IO::each_vertex
-///////////////////////////////////////////////////////////////////////////////
-%inline %{
-//! Thin wrapper for ONLY the increment operator
-void _vertices_incr(std::vector<meshio::pmd::Vertex>::const_iterator* iter)
-{
- // increment the iterator
- ++(*iter);
-}
-%}
-
-%extend meshio::pmd::IO {
-%pythoncode {
- def each_vertex(self):
- iter = self._beginVertices()
- while True:
- vertex = self._dereferenceVertex(iter)
- if vertex:
- _vertices_incr(iter)
- yield vertex
- else:
- break
-%}
-
-//! get the first element in the vector
-std::vector<meshio::pmd::Vertex>::const_iterator* _beginVertices()
-{
- return new std::vector<meshio::pmd::Vertex>::const_iterator(
- ($self->vertices.begin()));
-}
-
-//! dereference the iterator; return NULL if at the end
-const meshio::pmd::Vertex* _dereferenceVertex(
- const std::vector<meshio::pmd::Vertex>::const_iterator* iter )
-{
- // if at the end, return NULL
- if (*iter == ($self)->vertices.end() ) {
- return NULL;
- }
- // otherwise, return the face to which this iterator points
- return &(**iter);
-}
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// addVertex
-// addMaterial
-// addBone
-// addMorph
-// addIK
-// addBoneDisplay
-// addBoneGroup
-// getToonTexture
-// addRigidBody
-// addConstraint
-///////////////////////////////////////////////////////////////////////////////
-%extend meshio::pmd::IO {
-
-meshio::pmd::Vertex * addVertex()
-{
- $self->vertices.push_back(meshio::pmd::Vertex());
- return &($self->vertices.back());
-}
-
-meshio::pmd::Material *addMaterial()
-{
- $self->materials.push_back(new meshio::pmd::Material);
- return $self->materials.back();
-}
-
-meshio::pmd::Bone *addBone()
-{
- $self->bones.push_back(meshio::pmd::Bone());
- return &($self->bones.back());
-}
-
-meshio::pmd::Morph *addMorph()
-{
- $self->morph_list.push_back(meshio::pmd::Morph());
- return &($self->morph_list.back());
-}
-
-meshio::pmd::IK *addIK()
-{
- $self->ik_list.push_back(meshio::pmd::IK());
- return &($self->ik_list.back());
-}
-
-void addBoneDisplay(unsigned short bone_index, unsigned char display_index)
-{
- $self->bone_display_list.push_back(
- std::make_pair(bone_index, display_index));
-}
-
-meshio::pmd::BoneGroup *addBoneGroup()
-{
- $self->bone_group_list.push_back(meshio::pmd::BoneGroup());
- return &($self->bone_group_list.back());
-}
-
-meshio::pmd::ToonTexture *getToonTexture(int index)
-{
- return &($self->toon_textures[index]);
-}
-
-meshio::pmd::RigidBody *addRigidBody()
-{
- $self->rigidbodies.push_back(meshio::pmd::RigidBody());
- return &($self->rigidbodies.back());
-}
-
-meshio::pmd::Constraint *addConstraint()
-{
- $self->constraints.push_back(meshio::pmd::Constraint());
- return &($self->constraints.back());
-}
-
-}
-
+++ /dev/null
-#!/usr/bin/env python
-# coding: utf8
-"""
-日本語名との変換マップ
-"""
-import sys
-
-"""
-ボーン名変換
-"""
-boneMap=[
-("center", "センター", 1),
-("upper body", "上半身"),
-("neck", "首"),
-("head", "頭"),
-("eye_L", "左目", 5),
-("eye_R", "右目", 5),
-("necktie1", "ネクタイ1"),
-("necktie2", "ネクタイ2"),
-("necktie3", "ネクタイ3"),
-("lower body", "下半身"),
-("waist accessory", "腰飾り"),
-("hair1_L", "左髪1"),
-("hair2_L", "左髪2"),
-("hair3_L", "左髪3"),
-("hair4_L", "左髪4"),
-("hair5_L", "左髪5"),
-("hair6_L", "左髪6"),
-("shoulder_L", "左肩"),
-("arm_L", "左腕"),
-("arm twist_L", "左腕捩", 8),
-("elbow_L", "左ひじ"),
-("wrist twist_L", "左手捩", 8),
-("wrist_L", "左手首"),
-("sleeve_L", "左袖", 1),
-("thumb1_L", "左親指1"),
-("thumb2_L", "左親指2"),
-("fore1_L", "左人指1"),
-("fore2_L", "左人指2"),
-("fore3_L", "左人指3"),
-("middle1_L", "左中指1"),
-("middle2_L", "左中指2"),
-("middle3_L", "左中指3"),
-("third1_L", "左薬指1"),
-("third2_L", "左薬指2"),
-("third3_L", "左薬指3"),
-("little1_L", "左小指1"),
-("little2_L", "左小指2"),
-("little3_L", "左小指3"),
-("front skirt_L", "左スカート前"),
-("back skirt_L", "左スカート後"),
-("leg_L", "左足"),
-("knee_L", "左ひざ"),
-("ankle_L", "左足首"),
-("hair1_R", "右髪1"),
-("hair2_R", "右髪2"),
-("hair3_R", "右髪3"),
-("hair4_R", "右髪4"),
-("hair5_R", "右髪5"),
-("hair6_R", "右髪6"),
-("shoulder_R", "右肩"),
-("arm_R", "右腕"),
-("arm twist_R", "右腕捩", 8),
-("elbow_R", "右ひじ"),
-("wrist twist_R", "右手捩", 8),
-("wrist_R", "右手首"),
-("sleeve_R", "右袖", 1),
-("thumb1_R", "右親指1"),
-("thumb2_R", "右親指2"),
-("fore1_R", "右人指1"),
-("fore2_R", "右人指2"),
-("fore3_R", "右人指3"),
-("middle1_R", "右中指1"),
-("middle2_R", "右中指2"),
-("middle3_R", "右中指3"),
-("third1_R", "右薬指1"),
-("third2_R", "右薬指2"),
-("third3_R", "右薬指3"),
-("little1_R", "右小指1"),
-("little2_R", "右小指2"),
-("little3_R", "右小指3"),
-("front skirt_R", "右スカート前"),
-("back skirt_R", "右スカート後"),
-("leg_R", "右足"),
-("knee_R", "右ひざ"),
-("ankle_R", "右足首"),
-("eyes", "両目"),
-("front hair1", "前髪1"),
-("front hair2", "前髪2"),
-("front hair3", "前髪3"),
-("eyelight_L", "左目光"),
-("eyelight_R", "右目光"),
-("necktie3_t", "ネクタイ4"),
-("hair6_L_t", "左髪7"),
-("hair6_R_t", "右髪7"),
-("ankle_L_t", "左つま先"),
-("ankle_R_t", "右つま先"),
-("necktie IK", "ネクタイIK"),
-("hair IK_L", "左髪IK"),
-("hair IK_R", "右髪IK"),
-("leg IK_L", "左足IK"),
-("leg IK_R", "右足IK"),
-("toe IK_L", "左つま先IK"),
-("toe IK_R", "右つま先IK"),
-
-("lower body_t", "下半身先"),
-("head_t", "頭先"),
-("eye_L_t", "左目先"),
-("eye_R_t", "右目先"),
-("waist accessory_t", "腰飾り先"),
-
-("sleeve_L_t", "左袖先"),
-("wrist_L_t", "左手先"),
-("thumb2_L_t", "左親指先"),
-("fore3_L_t", "左人差指先"),
-("middle3_L_t", "左中指先"),
-("third3_L_t", "左薬指先"),
-("little3_L_t", "左小指先"),
-("front skirt_L_t", "左スカート前先"),
-("back skirt_L_t", "左スカート後先"),
-
-("sleeve_R_t", "右袖先"),
-("wrist_R_t", "右手先"),
-("thumb2_R_t", "右親指先"),
-("fore3_R_t", "右人差指先"),
-("middle3_R_t", "右中指先"),
-("third3_R_t", "右薬指先"),
-("little3_R_t", "右小指先"),
-("front skirt_R_t", "右スカート前先"),
-("back skirt_R_t", "右スカート後先"),
-
-("center_t", "センター先"),
-("eyes_t", "両目先"),
-("necktie IK_t", "ネクタイIK先"),
-("hair IK_L_t", "左髪IK先"),
-("hair IK_R_t", "右髪IK先"),
-("leg IK_L_t", "左足IK先"),
-("leg IK_R_t", "右足IK先"),
-("toe IK_L_t", "左つま先IK先"),
-("toe IK_R_t", "右つま先IK先"),
-("front hair1_t", "前髪1先"),
-("front hair2_t", "前髪2先"),
-("front hair3_t", "前髪3先"),
-("eyelight_L_t", "左目光先"),
-("eyelight_R_t", "右目光先"),
-("arm twist_L_t", "左腕捩先"),
-("wrist twist_L_t", "左手捩先"),
-("arm twist_R_t", "右腕捩先"),
-("wrist twist_R_t", "右手捩先"),
-("arm twist1_L", "左腕捩1", 9),
-("arm twist2_L", "左腕捩2", 9),
-("arm twist3_L", "左腕捩3", 9),
-("arm twist1_R", "右腕捩1", 9),
-("arm twist2_R", "右腕捩2", 9),
-("arm twist3_R", "右腕捩3", 9),
-#
-("arm twist1_L_t", "左腕捩1先"),
-("arm twist2_L_t", "左腕捩2先"),
-("arm twist3_L_t", "左腕捩3先"),
-("arm twist1_R_t", "右腕捩1先"),
-("arm twist2_R_t", "右腕捩2先"),
-("arm twist3_R_t", "右腕捩3先"),
-
-# 追加ボーン
-("root", "全ての親"),
-("root_t", "全ての親先"),
-("group", "グループ"),
-("group_t", "グループ先"),
-("front_shirt_L", "左シャツ前"),
-("front_shirt_R", "右シャツ前"),
-("back_shirt_L", "左シャツ後"),
-("back_shirt_R", "右シャツ後"),
-]
-def getEnglishBoneName(name):
- for v in boneMap:
- if v[1]==name:
- return v[0]
-
-def getIndexByEnglish(name):
- for i, v in enumerate(boneMap):
- if v[0]==name:
- return i
-
-def getUnicodeBoneName(name):
- for v in boneMap:
- if v[0]==name:
- return v
-
-"""
-モーフ名変換
-"""
-skinMap=[
-("base", "base", 0),
-("serious", "真面目", 1),
-("sadness", "困る", 1),
-("cheerful", "にこり", 1),
-("anger", "怒り", 1),
-("go up", "上", 1),
-("go down", "下", 1),
-("blink", "まばたき", 2),
-("smile", "笑い", 2),
-("wink", "ウィンク", 2),
-("wink2", "ウィンク2", 2),
-("wink_R", "ウィンク右", 2),
-("wink2_R", "ウィンク2右", 2),
-("close><", "はぅ", 2),
-("calm", "なごみ", 2),
-("surprise", "びっくり", 2),
-("doubt", "じと目", 2),
-("confuse", "なぬ!", 2),
-("pupil", "瞳小", 4),
-("a", "あ", 3),
-("i", "い", 3),
-("u", "う", 3),
-("o", "お", 3),
-("triangle", "▲", 3),
-("regret", "∧", 3),
-("omega", "ω", 3),
-("omegabox", "ω□", 3),
-("fool", "はんっ!", 3),
-("tongue", "ぺろっ", 4),
-("e-", "えー", 3),
-("grin", "にやり", 3),
-]
-def getEnglishSkinName(name):
- for v in skinMap:
- if v[1]==name:
- return v[0]
-
-def getUnicodeSkinName(name):
- for v in skinMap:
- if v[0]==name:
- return v
-
-"""
-ボーングループ名変換
-"""
-boneGroupMap=[
- ("IK", "IK"),
- ("Body[u]", "体(上)"),
- ("Hair", "髪"),
- ("Arms", "腕"),
- ("Fingers", "指"),
- ("Body[l]", "体(下)"),
- ("Legs", "足"),
- ]
-def getEnglishBoneGroupName(name):
- for v in boneGroupMap:
- if v[1]==name:
- return v[0]
-
-def getUnicodeBoneGroupName(name):
- for v in boneGroupMap:
- if v[0]==name:
- return v[1]
-
-
-###############################################################################
-# blender2.4 str to unicode
-###############################################################################
-if sys.version_info[0]<3:
- print('convert boneMap and skinMap to unicode...')
- # python2.x
- # unicodeに変換
- for i, l in enumerate(boneMap):
- replace=[]
- for j, m in enumerate(l):
- if j==1:
- replace.append(m.decode('utf-8'))
- else:
- replace.append(m)
- boneMap[i]=replace
-
- for i, l in enumerate(skinMap):
- replace=[]
- for j, m in enumerate(l):
- if j==1:
- replace.append(m.decode('utf-8'))
- else:
- replace.append(m)
- skinMap[i]=replace
- print('done')
-
+++ /dev/null
-#!/usr/bin/python
-# coding: utf-8
-"""
-20091202: VPD読み込みを追加
-20100318: PMD書き込みを追加
-20100731: meshioと互換になるように改造
-
-VMDの読み込み
-http://yumin3123.at.webry.info/200810/article_4.html
-http://atupdate.web.fc2.com/vmd_format.htm
-
-PMDの読み込み
-http://blog.goo.ne.jp/torisu_tetosuki/e/209ad341d3ece2b1b4df24abf619d6e4
-
-VPDの読み込み
-
-ToDo:
- rigdid bodies
- constraints
-"""
-import sys
-import codecs
-import os.path
-import struct
-import math
-import re
-#import numpy
-from decimal import *
-
-ENCODING='cp932'
-
-if sys.version_info[0]>=3:
- xrange=range
-
-###############################################################################
-# utility
-###############################################################################
-def truncate_zero(src):
- """
- 0x00以降を捨てる
- """
- pos = src.find(b"\x00")
- assert(type(src)==bytes)
- if pos >= 0:
- return src[:pos]
- else:
- return src
-
-def radian_to_degree(x):
- return x/math.pi * 180.0
-
-
-###############################################################################
-# geometry
-###############################################################################
-class Vector2(object):
- __slots__=['x', 'y']
- def __init__(self, x=0, y=0):
- self.x=x
- self.y=y
-
- def __str__(self):
- return "<%f %f>" % (self.x, self.y)
-
- def __getitem__(self, key):
- if key==0:
- return self.x
- elif key==1:
- return self.y
- else:
- assert(False)
-
- def to_tuple(self):
- return (self.x, self.y)
-
-
-class Vector3(object):
- __slots__=['x', 'y', 'z']
- def __init__(self, x=0, y=0, z=0):
- self.x=x
- self.y=y
- self.z=z
-
- def __str__(self):
- return "<%f %f %f>" % (self.x, self.y, self.z)
-
- def __getitem__(self, key):
- if key==0:
- return self.x
- elif key==1:
- return self.y
- elif key==2:
- return self.z
- else:
- assert(False)
-
- def to_tuple(self):
- return (self.x, self.y, self.z)
-
-class Quaternion(object):
- __slots__=['x', 'y', 'z', 'w']
- def __init__(self, x=0, y=0, z=0, w=1):
- self.x=x
- self.y=y
- self.z=z
- self.w=w
-
- def __str__(self):
- return "<%f %f %f %f>" % (self.x, self.y, self.z, self.w)
-
- def __mul__(self, rhs):
- u=numpy.array([self.x, self.y, self.z], 'f')
- v=numpy.array([rhs.x, rhs.y, rhs.z], 'f')
- xyz=self.w*v+rhs.w*u+numpy.cross(u, v)
- q=Quaternion(xyz[0], xyz[1], xyz[2], self.w*rhs.w-numpy.dot(u, v))
- return q
-
- def dot(self, rhs):
- return self.x*rhs.x+self.y*rhs.y+self.z*rhs.z+self.w*rhs.w
-
- def getMatrix(self):
- sqX=self.x*self.x
- sqY=self.y*self.y
- sqZ=self.z*self.z
- xy=self.x*self.y
- xz=self.x*self.z
- yz=self.y*self.z
- wx=self.w*self.x
- wy=self.w*self.y
- wz=self.w*self.z
- return numpy.array([
- # 1
- [1-2*sqY-2*sqZ, 2*xy+2*wz, 2*xz-2*wy, 0],
- # 2
- [2*xy-2*wz, 1-2*sqX-2*sqZ, 2*yz+2*wx, 0],
- # 3
- [2*xz+2*wy, 2*yz-2*wx, 1-2*sqX-2*sqY, 0],
- # 4
- [0, 0, 0, 1]],
- 'f')
-
- def getRHMatrix(self):
- x=-self.x
- y=-self.y
- z=self.z
- w=self.w
- sqX=x*x
- sqY=y*y
- sqZ=z*z
- xy=x*y
- xz=x*z
- yz=y*z
- wx=w*x
- wy=w*y
- wz=w*z
- return numpy.array([
- # 1
- [1-2*sqY-2*sqZ, 2*xy+2*wz, 2*xz-2*wy, 0],
- # 2
- [2*xy-2*wz, 1-2*sqX-2*sqZ, 2*yz+2*wx, 0],
- # 3
- [2*xz+2*wy, 2*yz-2*wx, 1-2*sqX-2*sqY, 0],
- # 4
- [0, 0, 0, 1]],
- 'f')
-
- def getRollPitchYaw(self):
- m=self.getMatrix()
-
- roll = math.atan2(m[0, 1], m[1, 1])
- pitch = math.asin(-m[2, 1])
- yaw = math.atan2(m[2, 0], m[2, 2])
-
- if math.fabs(math.cos(pitch)) < 1.0e-6:
- roll += m[0, 1] > math.pi if 0.0 else -math.pi
- yaw += m[2, 0] > math.pi if 0.0 else -math.pi
-
- return roll, pitch, yaw
-
- def getSqNorm(self):
- return self.x*self.x+self.y*self.y+self.z*self.z+self.w*self.w
-
- def getNormalized(self):
- f=1.0/self.getSqNorm()
- q=Quaternion(self.x*f, self.y*f, self.z*f, self.w*f)
- return q
-
- def getRightHanded(self):
- "swap y and z axis"
- return Quaternion(-self.x, -self.z, -self.y, self.w)
-
- @staticmethod
- def createFromAxisAngle(axis, rad):
- q=Quaternion()
- half_rad=rad/2.0
- c=math.cos(half_rad)
- s=math.sin(half_rad)
- return Quaternion(axis[0]*s, axis[1]*s, axis[2]*s, c)
-
-
-class RGBA(object):
- __slots__=['r', 'g', 'b', 'a']
- def __init__(self, r=0, g=0, b=0, a=1):
- self.r=r
- self.g=g
- self.b=b
- self.a=a
-
- def __getitem__(self, key):
- if key==0:
- return self.r
- elif key==1:
- return self.g
- elif key==2:
- return self.b
- elif key==3:
- return self.a
- else:
- assert(False)
-
-
-###############################################################################
-# VMD
-###############################################################################
-class ShapeData(object):
- __slots__=['name', 'frame', 'ratio']
- def __init__(self, name):
- self.name=name
- self.frame=-1
- self.ratio=0
-
- def __cmp__(self, other):
- return cmp(self.frame, other.frame)
-
-class MotionData(object):
- __slots__=['name', 'frame', 'pos', 'q', 'complement']
- def __init__(self, name):
- self.name=name
- self.frame=-1
- self.pos=Vector3()
- self.q=Quaternion()
-
- def __cmp__(self, other):
- return cmp(self.frame, other.frame)
-
- def __str__(self):
- return '<MotionData "%s" %d %s%s>' % (self.name, self.frame, self.pos, self.q)
-
-class VMDLoader(object):
- __slots__=['io', 'end', 'signature',
- 'model_name', 'last_frame',
- 'motions', 'shapes', 'cameras', 'lights',
- ]
- def __init__(self):
- self.model_name=''
- self.motions=[]
- self.shapes=[]
- self.cameras=[]
- self.lights=[]
- self.last_frame=0
-
- def __str__(self):
- return '<VMDLoader model: "%s", motion: %d, shape: %d, camera: %d, light: %d>' % (
- self.model_name, len(self.motions), len(self.shapes),
- len(self.cameras), len(self.lights))
-
- def load(self, path, io, end):
- self.io=io
- self.end=end
-
- # signature
- self.signature=truncate_zero(self.io.read(30))
- version=self.validate_signature(self.signature)
- if not version:
- print("invalid signature", self.signature)
- return False
-
- if version==1:
- if not self.load_verstion_1():
- return False
- elif version==2:
- if not self.load_verstion_2():
- return False
- else:
- raise Exception("unknown version")
-
- # post process
- motions=self.motions
- self.motions={}
- for m in motions:
- if not m.name in self.motions:
- self.motions[m.name]=[]
- self.motions[m.name].append(m)
- for name in self.motions.keys():
- self.motions[name].sort()
-
- shapes=self.shapes
- self.shapes={}
- for s in shapes:
- if not s.name in self.shapes:
- self.shapes[s.name]=[]
- self.shapes[s.name].append(s)
- for name in self.shapes.keys():
- self.shapes[name].sort()
-
- return True
-
- def getMotionCount(self):
- count=0
- for v in self.motions.values():
- count+=len(v)
- return count
-
- def getShapeCount(self):
- count=0
- for v in self.shapes.values():
- count+=len(v)
- return count
-
- def load_verstion_1(self):
- # model name
- self.model_name=truncate_zero(self.io.read(10))
- if not self.loadMotion_1():
- return False
- return True
-
- def loadMotion_1(self):
- count=struct.unpack('H', self.io.read(2))[0]
- self.io.read(2)
- for i in xrange(0, count):
- self.loadFrameData()
- return True
-
- ############################################################
- def load_verstion_2(self):
- # model name
- self.model_name=truncate_zero(self.io.read(20))
-
- if not self.loadMotion():
- return False
- if not self.loadShape():
- return False
- if not self.loadCamera():
- return False
- if not self.loadLight():
- return False
- #assert(self.io.tell()==self.end)
- #self.motions.sort(lambda l, r: l.name<r.name)
-
- return True
-
- def validate_signature(self, signature):
- if self.signature == "Vocaloid Motion Data 0002":
- return 2
- if self.signature == "Vocaloid Motion Data file":
- return 1
- else:
- return None
-
- def loadMotion(self):
- count=struct.unpack('I', self.io.read(4))[0]
- for i in xrange(0, count):
- self.loadFrameData()
- return True
-
- def loadShape(self):
- count=struct.unpack('I', self.io.read(4))[0]
- for i in xrange(0, count):
- self.loadShapeData()
- return True
-
- def loadCamera(self):
- count=struct.unpack('I', self.io.read(4))[0]
- for i in xrange(0, count):
- # not implemented
- assert(False)
- pass
- return True
-
- def loadLight(self):
- count=struct.unpack('I', self.io.read(4))[0]
- for i in xrange(0, count):
- # not implemented
- assert(False)
- pass
- return True
-
- def loadFrameData(self):
- """
- フレームひとつ分を読み込む
- """
- data=MotionData(truncate_zero(self.io.read(15)))
- (data.frame, data.pos.x, data.pos.y, data.pos.z,
- data.q.x, data.q.y, data.q.z, data.q.w) = struct.unpack(
- 'I7f', self.io.read(32))
- # complement data
- data.complement=''.join(
- ['%x' % x for x in struct.unpack('64B', self.io.read(64))])
- self.motions.append(data)
- if data.frame>self.last_frame:
- self.last_frame=data.frame
-
- def loadShapeData(self):
- """
- モーフデータひとつ分を読み込む
- """
- data=ShapeData(truncate_zero(self.io.read(15)))
- (data.frame, data.ratio)=struct.unpack('If', self.io.read(8))
- self.shapes.append(data)
- if data.frame>self.last_frame:
- self.last_frame=data.frame
-
- # vmd -> csv
- ############################################################
- def create_csv_line(m):
- # quaternion -> euler angle
- (roll, pitch, yaw)=m.q.getRollPitchYaw()
- return '%s,%d,%g,%g,%g,%g,%g,%g,0x%s\n' % (
- m.name, m.frame, m.pos.x, m.pos.y, m.pos.z,
- to_degree(pitch), to_degree(yaw), to_degree(roll), m.complement
- )
-
- def write_csv(l, path):
- sys.setdefaultencoding('cp932')
- csv=open(path, "w")
- csv.write('%s,0\n' % l.signature)
- csv.write('%s\n' % l.model_name)
- # motion
- csv.write('%d\n' % len(l.motions))
- for m in l.motions:
- csv.write(create_csv_line(m))
- # shape
- csv.write('%d\n' % len(l.shapes))
- for s in l.shapes:
- csv.write('%s,%d,%f\n' % ( s.name, s.frame, s.ratio))
- # camera
- csv.write('%d\n' % len(l.cameras))
- for camera in l.cameras:
- assert(False)
- # light
- csv.write('%d\n' % len(l.lights))
- for light in l.lights:
- assert(False)
-
-
-###############################################################################
-# PMD
-###############################################################################
-class Vertex(object):
- __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.pos=Vector3(x, y, z)
- self.normal=Vector3(nx, ny, nz)
- self.uv=Vector2(u, v)
- self.bone0=bone0
- self.bone1=bone1
- self.weight0=weight0
- 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)
-
- def __getitem__(self, key):
- if key==0:
- return self.pos.x
- elif key==1:
- return self.pos.y
- elif key==2:
- return self.pos.z
- else:
- assert(False)
-
-class Material(object):
- __slots__=[
- 'diffuse', 'shinness', 'specular',
- 'ambient', 'vertex_count', 'texture', 'toon_index', 'flag',
- ]
-
- def __init__(self, dr=0, dg=0, db=0, alpha=1,
- specular=0, sr=0, sg=0, sb=0, ar=0, ag=0, ab=0):
- self.diffuse=RGBA(dr, dg, db, alpha)
- self.specular=RGBA(sr, sg, sb)
- self.shinness=specular
- self.ambient=RGBA(ar, ag, ab)
- self.vertex_count=0
- self.texture=''
- self.toon_index=0
- self.flag=0
-
- def __str__(self):
- return "<Material [%f, %f, %f, %f]>" % (
- self.diffuse[0], self.diffuse[1],
- self.diffuse[2], self.diffuse[3],
- )
-
- def getTexture(self): return self.texture.decode('cp932')
- def setTexture(self, u): self.texture=u
-
-# @return 各マテリアルについて、そのマテリアルが保持する面の回数だけ
-# マテリアル自身を返す
-def material_per_face(materials):
- for m in materials:
- for x in xrange(int(m.vertex_count/3)):
- yield m
-
-class Bone(object):
- # kinds
- ROTATE = 0
- ROTATE_MOVE = 1
- IK = 2
- IK_ROTATE_INFL = 4
- ROTATE_INFL = 5
- IK_TARGET = 6
- UNVISIBLE = 7
- # since v4.0
- ROLLING=8 # ?
- TWEAK=9
- __slots__=['name', 'index', 'type', 'parent', 'ik', 'pos',
- 'children', 'english_name', 'ik_index',
- 'parent_index', 'tail_index', 'tail',
- ]
- def __init__(self, name='bone', type=0):
- self.name=name
- self.index=0
- self.type=type
- self.parent_index=0xFFFF
- self.tail_index=0
- self.tail=Vector3(0, 0, 0)
- self.parent=None
- self.ik_index=0xFFFF
- self.pos=Vector3(0, 0, 0)
- self.children=[]
- self.english_name=''
-
- def getName(self): return self.name.decode('cp932')
- def setName(self, u): self.name=u
- def setEnglishName(self, u): self.english_name=u
-
- def hasParent(self):
- return self.parent_index!=0xFFFF
-
- def hasChild(self):
- return self.tail_index!=0
-
- def display(self, indent=[]):
- if len(indent)>0:
- prefix=''
- for i, is_end in enumerate(indent):
- if i==len(indent)-1:
- break
- else:
- prefix+=' ' if is_end else ' |'
- uni='%s +%s(%s)' % (prefix, unicode(self), self.english_name)
- print(uni.encode(ENCODING))
- else:
- uni='%s(%s)' % (unicode(self), self.english_name)
- print(uni.encode(ENCODING))
-
- child_count=len(self.children)
- for i in xrange(child_count):
- child=self.children[i]
- if i<child_count-1:
- child.display(indent+[False])
- else:
- # last
- child.display(indent+[True])
-
-# 0
-class Bone_Rotate(Bone):
- __slots__=[]
- def __init__(self, name):
- super(Bone_Rotate, self).__init__(name, 0)
- def __str__(self):
- return '<ROTATE %s>' % (self.name)
-# 1
-class Bone_RotateMove(Bone):
- __slots__=[]
- def __init__(self, name):
- super(Bone_RotateMove, self).__init__(name, 1)
- def __str__(self):
- return '<ROTATE_MOVE %s>' % (self.name)
-# 2
-class Bone_IK(Bone):
- __slots__=[]
- def __init__(self, name):
- super(Bone_IK, self).__init__(name, 2)
- def __str__(self):
- return '<IK %s>' % (self.name)
-# 4
-class Bone_IKRotateInfl(Bone):
- __slots__=[]
- def __init__(self, name):
- super(Bone_IKRotateInfl, self).__init__(name, 4)
- def __str__(self):
- return '<IK_ROTATE_INFL %s>' % (self.name)
-# 5
-class Bone_RotateInfl(Bone):
- __slots__=[]
- def __init__(self, name):
- super(Bone_RotateInfl, self).__init__(name, 5)
- def __str__(self):
- return '<ROTATE_INFL %s>' % (self.name)
-# 6
-class Bone_IKTarget(Bone):
- __slots__=[]
- def __init__(self, name):
- super(Bone_IKTarget, self).__init__(name, 6)
- def __str__(self):
- return '<IK_TARGET %s>' % (self.name)
-# 7
-class Bone_Unvisible(Bone):
- __slots__=[]
- def __init__(self, name):
- super(Bone_Unvisible, self).__init__(name, 7)
- def __str__(self):
- return '<UNVISIBLE %s>' % (self.name)
-# 8
-class Bone_Rolling(Bone):
- __slots__=[]
- def __init__(self, name):
- super(Bone_Rolling, self).__init__(name, 8)
- def __str__(self):
- return '<ROLLING %s>' % (self.name)
-# 9
-class Bone_Tweak(Bone):
- __slots__=[]
- def __init__(self, name):
- super(Bone_Tweak, self).__init__(name, 9)
- def __str__(self):
- return '<TWEAK %s>' % (self.name)
-
-
-def createBone(name, type):
- if type==0:
- return Bone_Rotate(name)
- elif type==1:
- return Bone_RotateMove(name)
- elif type==2:
- return Bone_IK(name)
- elif type==3:
- raise Exception("no used bone type: 3(%s)" % name)
- elif type==4:
- return Bone_IKRotateInfl(name)
- elif type==5:
- return Bone_RotateInfl(name)
- elif type==6:
- return Bone_IKTarget(name)
- elif type==7:
- return Bone_Unvisible(name)
- elif type==8:
- return Bone_Rolling(name)
- elif type==9:
- return Bone_Tweak(name)
- else:
- raise Exception("unknown bone type: %d(%s)", type, name)
-
-
-class IK(object):
- __slots__=['index', 'target', 'iterations', 'weight', 'length', 'children']
- def __init__(self, index=0, target=0):
- self.index=index
- self.target=target
- self.iterations=None
- self.weight=None
- self.children=[]
-
- def __str__(self):
- return "<IK index: %d, target: %d, iterations: %d, weight: %f, children: %s(%d)>" %(self.index, self.target, self.iterations, self.weight, '-'.join([str(i) for i in self.children]), len(self.children))
-
-class Skin(object):
- __slots__=['name', 'type', 'indices', 'pos_list', 'english_name',
- 'vertex_count']
- def __init__(self, name='skin'):
- self.name=name
- self.type=None
- self.indices=[]
- self.pos_list=[]
- self.english_name=''
- self.vertex_count=0
-
- def getName(self): return self.name.decode('cp932')
- def setName(self, u): self.name=u
- def setEnglishName(self, u): self.english_name=u
-
- def append(self, index, x, y, z):
- self.indices.append(index)
- self.pos_list.append(Vector3(x, y, z))
-
- def __str__(self):
- return '<Skin name: "%s", type: %d, vertex: %d>' % (
- self.name, self.type, len(self.indices))
-
-class ToonTexture(object):
- __slots__=['name']
- def __init__(self, name): self.name=name
- def getName(self): return self.name.decode('cp932')
- def setName(self, u): self.name=u
-
-class BoneGroup(object):
- __slots__=['name', 'english_name']
- def __init__(self, name='group'): self.name=name; self.english_name='center'
- def getName(self): return self.name.decode('cp932')
- def setName(self, u): self.name=u
- def getEnglishName(self): return self.english_name.decode('cp932')
- def setEnglishName(self, u): self.english_name=u
-
-class PMDLoader(object):
- __slots__=['io', 'end', 'pos',
- 'version', 'model_name', 'comment',
- 'english_model_name', 'english_comment',
- 'vertices', 'indices', 'materials', 'bones',
- 'ik_list', 'morph_list',
- 'face_list', 'bone_group_list', 'bone_display_list',
- 'toon_textures',
- 'no_parent_bones',
- 'rigidbodies', 'constraints',
- ]
- def __init__(self):
- self.version=1.0
- self.model_name=b"default"
- self.comment=b"default"
- self.english_model_name=b'default'
- self.english_comment=b'default'
- self.vertices=[]
- self.indices=[]
- self.materials=[]
- self.bones=[]
- self.ik_list=[]
- self.morph_list=[]
-
- self.face_list=[]
- self.bone_group_list=[]
- self.bone_display_list=[]
-
- self.toon_textures=[
- ToonTexture(b'toon'), ToonTexture(b'toon'),
- ToonTexture(b'toon'), ToonTexture(b'toon'),
- ToonTexture(b'toon'), ToonTexture(b'toon'),
- ToonTexture(b'toon'), ToonTexture(b'toon'),
- ToonTexture(b'toon'), ToonTexture(b'toon'),
- ]
-
- self.no_parent_bones=[]
-
- self.rigidbodies=[]
- self.constraints=[]
-
- def getName(self): return self.model_name.decode('cp932')
- def setName(self, u): self.model_name=u
- def getComment(self): return self.comment.decode('cp932')
- def setComment(self, u): self.comment=u
- def getEnglishName(self): return self.english_model_name.decode('cp932')
- def setEnglishName(self, u): self.english_model_name=u
- def getEnglishComment(self): return self.english_comment.decode('cp932')
- def setEnglishComment(self, u): self.english_comment=u
-
- def getToonTexture(self, i): return self.toon_textures[i]
- def each_vertex(self): return self.vertices
- def getUV(self, i): return self.vertices[i].uv
- def addVertex(self):
- v=Vertex()
- self.vertices.append(v)
- return v
- def addMaterial(self):
- m=Material()
- self.materials.append(m)
- return m
- def addBone(self):
- b=Bone()
- self.bones.append(b)
- return b
- def addIK(self):
- ik=IK()
- self.ik_list.append(ik)
- return ik
- def addMorph(self):
- s=Skin()
- self.morph_list.append(s)
- return s
- def addBoneGroup(self):
- g=BoneGroup()
- self.bone_group_list.append(g)
- return g
- def addBoneDisplay(self, b, g):
- self.bone_display_list.append((b, g))
-
- def __str__(self):
- return '<PMDLoader version: %g, model: "%s", vertex: %d, face: %d, material: %d, bone: %d ik: %d, skin: %d>' % (
- self.version, self.model_name, len(self.vertices), len(self.indices),
- len(self.materials), len(self.bones), len(self.ik_list), len(self.morph_list))
-
- def _check_position(self):
- """
- if self.pos:
- print(self.pos, self.io.tell()-self.pos)
- """
- self.pos=self.io.tell()
- pass
-
- def read(self, path):
- size=os.path.getsize(path)
- f=open(path, "rb")
- return self.load(path, f, size)
-
- def load(self, path, io, end):
- self.io=io
- self.pos=self.io.tell()
- self.end=end
- self._check_position()
-
- if not self._loadHeader():
- return False
- self._check_position()
-
- if not self._loadVertex():
- return False
- self._check_position()
-
- if not self._loadFace():
- return False
- self._check_position()
-
- if not self._loadMaterial():
- return False
- self._check_position()
-
- if not self._loadBone():
- return False
- self._check_position()
-
- if not self._loadIK():
- return False
- self._check_position()
-
- if not self._loadSkin():
- return False
- self._check_position()
-
- if not self._loadSkinIndex():
- return False
- self._check_position()
-
- if not self._loadBoneName():
- return False
- self._check_position()
-
- if not self._loadBoneIndex():
- return False
- self._check_position()
-
- if not self._loadExtend():
- print('fail to loadExtend')
- return False
-
- # 終端
- if self.io.tell()!=self.end:
- print("can not reach eof.")
- print("current: %d, end: %d, remain: %d" % (
- self.io.tell(), self.end, self.end-self.io.tell()))
-
- # build bone tree
- for i, child in enumerate(self.bones):
- if child.parent_index==0xFFFF:
- # no parent
- self.no_parent_bones.append(child)
- child.parent=None
- else:
- # has parent
- parent=self.bones[child.parent_index]
- child.parent=parent
- parent.children.append(child)
- # 後位置
- if child.hasChild():
- child.tail=self.bones[child.tail_index].pos
-
- return True
-
- def write(self, path):
- io=open(path, 'wb')
- if not io:
- return False
- # Header
- io.write(b"Pmd")
- io.write(struct.pack("f", self.version))
- io.write(struct.pack("20s", self.model_name))
- io.write(struct.pack("256s", self.comment))
-
- # Vertices
- io.write(struct.pack("I", len(self.vertices)))
- sVertex=struct.Struct("=8f2H2B") # 38byte
- assert(sVertex.size==38)
- for v in self.vertices:
- data=sVertex.pack(
- v.pos[0], v.pos[1], v.pos[2],
- v.normal[0], v.normal[1], v.normal[2],
- v.uv[0], v.uv[1],
- v.bone0, v.bone1, v.weight0, v.edge_flag)
- io.write(data)
-
- # Faces
- io.write(struct.pack("I", len(self.indices)))
- io.write(struct.pack("=%dH" % len(self.indices), *self.indices))
-
- # material
- io.write(struct.pack("I", len(self.materials)))
- sMaterial=struct.Struct("=3fff3f3fBBI20s") # 70byte
- assert(sMaterial.size==70)
- for m in self.materials:
- io.write(sMaterial.pack(
- m.diffuse[0], m.diffuse[1], m.diffuse[2], m.diffuse[3],
- m.shinness,
- m.specular[0], m.specular[1], m.specular[2],
- m.ambient[0], m.ambient[1], m.ambient[2],
- m.toon_index, m.flag,
- m.vertex_count,
- m.texture
- ))
-
- # bone
- io.write(struct.pack("H", len(self.bones)))
- sBone=struct.Struct("=20sHHBH3f")
- assert(sBone.size==39)
- for b in self.bones:
- io.write(sBone.pack(
- b.name,
- b.parent_index, b.tail_index, b.type, b.ik_index,
- b.pos[0], b.pos[1], b.pos[2]))
-
- # IK
- io.write(struct.pack("H", len(self.ik_list)))
- for ik in self.ik_list:
- io.write(struct.pack("=2HBHf",
- ik.index, ik.target, ik.length, ik.iterations, ik.weight
- ))
- for c in ik.children:
- io.write(struct.pack("H", c))
-
- # skin
- io.write(struct.pack("H", len(self.morph_list)))
- for s in self.morph_list:
- io.write(struct.pack("20sIB",
- s.name, len(s.indices), s.type))
- for i, v in zip(s.indices, s.pos_list):
- io.write(struct.pack("I3f", i, v[0], v[1], v[2]))
-
- # skin list
- io.write(struct.pack("B", len(self.face_list)))
- for i in self.face_list:
- io.write(struct.pack("H", i))
-
- # bone name
- io.write(struct.pack("B", len(self.bone_group_list)))
- for g in self.bone_group_list:
- io.write(struct.pack("50s", g.name))
-
- # bone list
- io.write(struct.pack("I", len(self.bone_display_list)))
- for l in self.bone_display_list:
- io.write(struct.pack("=HB", *l))
-
- # ToDo
- # Extend Data
-
- return True
-
-
- def _loadExtend(self):
- ############################################################
- # extend1: english name
- ############################################################
- if self.io.tell()>=self.end:
- return True
- if struct.unpack("B", self.io.read(1))[0]==1:
- if not self.loadEnglishName():
- return False
- self._check_position()
-
- ############################################################
- # extend2: toon texture list
- ############################################################
- if self.io.tell()>=self.end:
- return True
- if not self.loadToonTexture():
- return False
- self._check_position()
-
- ############################################################
- # extend3: physics
- ############################################################
- if self.io.tell()>=self.end:
- return True
- #if not self.loadPhysics():
- # return False
- self._check_position()
-
- return True
-
- def _loadHeader(self):
- signature=struct.unpack("3s", self.io.read(3))[0]
- print(signature)
- if signature!=b"Pmd":
- print("invalid signature", signature)
- return False
- self.version=struct.unpack("f", self.io.read(4))[0]
- self.model_name = truncate_zero(struct.unpack("20s", self.io.read(20))[0])
- self.comment = truncate_zero(
- struct.unpack("256s", self.io.read(256))[0])
- return True
-
- def _loadVertex(self):
- count = struct.unpack("I", self.io.read(4))[0]
- for i in xrange(count):
- self.vertices.append(Vertex(*struct.unpack("8f2H2B", self.io.read(38))))
- return True
-
- def _loadFace(self):
- count = struct.unpack("I", self.io.read(4))[0]
- for i in xrange(0, count, 3):
- self.indices+=struct.unpack("HHH", self.io.read(6))
- return True
-
- def _loadMaterial(self):
- count = struct.unpack("I", self.io.read(4))[0]
- for i in xrange(count):
- material=Material(*struct.unpack("4ff3f3f", self.io.read(44)))
- material.toon_index=struct.unpack("B", self.io.read(1))[0]
- material.flag=struct.unpack("B", self.io.read(1))[0]
- material.vertex_count=struct.unpack("I", self.io.read(4))[0]
- texture=truncate_zero(struct.unpack("20s", self.io.read(20))[0])
- # todo sphere map
- #material.texture=texture.split('*')[0]
- material.texture=texture
- self.materials.append(material)
- return True
-
- def _loadBone(self):
- size = struct.unpack("H", self.io.read(2))[0]
- for i in xrange(size):
- name=truncate_zero(struct.unpack("20s", self.io.read(20))[0])
- parent_index, tail_index = struct.unpack("HH", self.io.read(4))
- type = struct.unpack("B", self.io.read(1))[0]
- bone=createBone(name, type)
- bone.parent_index=parent_index
- bone.tail_index=tail_index
- bone.ik_index = struct.unpack("H", self.io.read(2))[0]
- bone.pos = Vector3(*struct.unpack("3f", self.io.read(12)))
- bone.english_name="bone%03d" % len(self.bones)
- self.bones.append(bone)
- return True
-
- def _loadIK(self):
- size = struct.unpack("H", self.io.read(2))[0]
- for i in xrange(size):
- ik=IK(*struct.unpack("2H", self.io.read(4)))
- ik.length = struct.unpack("B", self.io.read(1))[0]
- ik.iterations = struct.unpack("H", self.io.read(2))[0]
- ik.weight = struct.unpack("f", self.io.read(4))[0]
- for j in xrange(ik.length):
- ik.children.append(struct.unpack("H", self.io.read(2))[0])
- self.ik_list.append(ik)
- return True
-
- def _loadSkin(self):
- size = struct.unpack("H", self.io.read(2))[0]
- for i in xrange(size):
- skin=Skin(truncate_zero(struct.unpack("20s", self.io.read(20))[0]))
- skin_size = struct.unpack("I", self.io.read(4))[0]
- skin.type = struct.unpack("B", self.io.read(1))[0]
- for j in xrange(skin_size):
- skin.indices.append(struct.unpack("I", self.io.read(4))[0])
- skin.pos_list.append(
- Vector3(*struct.unpack("3f", self.io.read(12))))
- skin.english_name="skin%03d" % len(self.morph_list)
- self.morph_list.append(skin)
- return True
-
- def _loadSkinIndex(self):
- size = struct.unpack("B", self.io.read(1))[0]
- for i in xrange(size):
- self.face_list.append(struct.unpack("H", self.io.read(2))[0])
- return True
-
- def _loadBoneName(self):
- size = struct.unpack("B", self.io.read(1))[0]
- for i in xrange(size):
- self.bone_group_list.append(BoneGroup(
- truncate_zero(struct.unpack("50s", self.io.read(50))[0])))
- return True
-
- def _loadBoneIndex(self):
- size = struct.unpack("I", self.io.read(4))[0]
- for i in xrange(size):
- self.bone_display_list.append(struct.unpack("HB", self.io.read(3)))
- return True
-
- def loadToonTexture(self):
- """
- 100bytex10
- """
- for i in xrange(10):
- self.toon_textures.append(ToonTexture(
- truncate_zero(struct.unpack("100s", self.io.read(100))[0])))
- return True
-
- def loadEnglishName(self):
- # english name
- self.english_model_name=truncate_zero(
- struct.unpack("20s", self.io.read(20))[0])
- self.english_comment=truncate_zero(
- struct.unpack("256s", self.io.read(256))[0])
- # english bone list
- for bone in self.bones:
- english_name=truncate_zero(
- struct.unpack("20s", self.io.read(20))[0])
- if english_name!=bone.name:
- bone.english_name=english_name
- # english skin list
- #for index in self.face_list:
- for skin in self.morph_list:
- if skin.name=='base':
- continue
- english_name=truncate_zero(
- struct.unpack("20s", self.io.read(20))[0])
- #skin=self.morph_list[index]
- if english_name!=skin.name:
- skin.english_name=english_name
- # english bone list
- for i in xrange(0, len(self.bone_group_list)):
- self.bone_group_list[i].english_name=truncate_zero(
- struct.unpack("50s", self.io.read(50))[0])
- return True
-
- def loadPhysics(self):
- # 剛体リスト
- count = struct.unpack("I", self.io.read(4))[0]
- for i in xrange(count):
- struct.unpack("83s", self.io.read(83))[0]
- # ジョイントリスト
- count = struct.unpack("I", self.io.read(4))[0]
- for i in xrange(count):
- struct.unpack("124s", self.io.read(124))[0]
- return True
-
-
-###############################################################################
-# VPD
-###############################################################################
-class LineLoader(object):
- """
- 行指向の汎用ローダ
- """
- __slots__=['path', 'io', 'end']
- def __str__(self):
- return "<%s current:%d, end:%d>" % (
- self.__class__, self.getPos(), self.getEnd())
-
- def getPos(self):
- return self.io.tell()
-
- def getEnd(self):
- return self.end
-
- def readline(self):
- return (self.io.readline()).strip()
-
- def isEnd(self):
- return self.io.tell()>=self.end
-
- def load(self, path, io, end):
- self.path=path
- self.io=io
- self.end=end
- return self.process()
-
- def process(self):
- """
- dummy. read to end.
- """
- while not self.isEnd():
- self.io.readline()
- return True
-
-
-class VPDLoader(LineLoader):
- __slots__=['pose']
- def __init__(self):
- super(VPDLoader, self).__init__()
- self.pose=[]
-
- def __str__(self):
- return "<VPD poses:%d>" % len(self.pose)
-
- def process(self):
- if self.readline()!="Vocaloid Pose Data file":
- return
-
- RE_OPEN=re.compile('^(\w+){(.*)')
- RE_OSM=re.compile('^\w+\.osm;')
- RE_COUNT=re.compile('^(\d+);')
-
- bone_count=-1
- while not self.isEnd():
- line=self.readline()
- if line=='':
- continue
- m=RE_OPEN.match(line)
- if m:
- if not self.parseBone(m.group(2)):
- raise Exception("invalid bone")
- continue
-
- m=RE_OSM.match(line)
- if m:
- continue
-
- m=RE_COUNT.match(line)
- if m:
- bone_count=int(m.group(1))
- continue
-
- return len(self.pose)==bone_count
-
- def parseBone(self, name):
- bone=MotionData(name)
- self.pose.append(bone)
- bone.pos=Vector3(*[float(token) for token in self.readline().split(';')[0].split(',')])
- bone.q=Quaternion(*[float(token) for token in self.readline().split(';')[0].split(',')])
- return self.readline()=="}"
-
-
-###############################################################################
-# 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()
-
+++ /dev/null
-#!BPY\r
-""" \r
-Name: 'Metasequoia(.mqo)...'\r
-Blender: 245\r
-Group: 'Import'\r
-Tooltip: 'Import from Metasequoia file format (.mqo)'\r
-"""\r
-__author__= 'ousttrue'\r
-__url__ = ["http://gunload.web.fc2.com/blender/"]\r
-__version__= '0.4 2009/11/25'\r
-__bpydoc__= '''\\r
-\r
-MQO Importer\r
-\r
-This script imports a mqo file.\r
-\r
-0.2 20080123: update.\r
-0.3 20091125: modify for linux.\r
-0.4 20100310: rewrite.\r
-0.5 20100311: create armature from mikoto bone.\r
-'''\r
-\r
-import os\r
-import sys\r
-import math\r
-\r
-\r
-class RGBA(object):\r
- __slots__=['r', 'g', 'b', 'a']\r
- def __init__(self, r=0, g=0, b=0, a=0):\r
- self.r=r\r
- self.g=g\r
- self.b=b\r
- self.a=a\r
-\r
-class Vector3(object):\r
- __slots__=['x', 'y', 'z']\r
- def __init__(self, x=0, y=0, z=0):\r
- self.x=x\r
- self.y=y\r
- self.z=z\r
-\r
- def __str__(self):\r
- return "[%f, %f, %f]" % (self.x, self.y, self.z)\r
-\r
- def __sub__(self, rhs):\r
- return Vector3(self.x-rhs.x, self.y-rhs.y, self.z-rhs.z)\r
-\r
- def getSqNorm(self):\r
- return self.x*self.x + self.y*self.y + self.z*self.z\r
-\r
- def getNorm(self):\r
- return math.sqrt(self.getSqNorm())\r
-\r
- def normalize(self):\r
- factor=1.0/self.getNorm()\r
- self.x*=factor\r
- self.y*=factor\r
- self.z*=factor\r
- return self\r
-\r
- def to_a(self):\r
- return [self.x, self.y, self.z]\r
-\r
- @staticmethod\r
- def dot(lhs, rhs):\r
- return lhs.x*rhs.x + lhs.y*rhs.y + lhs.z*rhs.z\r
-\r
- @staticmethod\r
- def cross(lhs, rhs):\r
- return Vector3(\r
- lhs.y*rhs.z - rhs.y*lhs.z,\r
- lhs.z*rhs.x - rhs.z*lhs.x,\r
- lhs.x*rhs.y - rhs.x*lhs.y,\r
- )\r
-\r
-\r
-class Vector2(object):\r
- __slots__=['x', 'y']\r
- def __init__(self, x=0, y=0):\r
- self.x=x\r
- self.y=y\r
-\r
- def __str__(self):\r
- return "[%f, %f]" % (self.x, self.y)\r
-\r
- def __sub__(self, rhs):\r
- return Vector3(self.x-rhs.x, self.y-rhs.y)\r
-\r
- @staticmethod\r
- def cross(lhs, rhs):\r
- return lhs.x*rhs.y-lhs.y*rhs.x\r
-\r
-\r
-###############################################################################\r
-# MQO loader\r
-###############################################################################\r
-class Material(object):\r
- __slots__=[\r
- "name", "shader", "color", "diffuse", \r
- "ambient", "emit", "specular", "power",\r
- "tex",\r
- ]\r
- def __init__(self, name):\r
- self.name=name\r
- self.shader=3\r
- self.color=RGBA(0.5, 0.5, 0.5, 1.0)\r
- self.diffuse=1.0\r
- self.ambient=0.0\r
- self.emit=0.0\r
- self.specular=0.0\r
- self.power=5.0\r
- self.tex=""\r
-\r
- def getName(self): return self.name\r
- def getTexture(self): return self.tex\r
-\r
- def parse(self, line):\r
- offset=0\r
- while True:\r
- leftParenthesis=line.find("(", offset)\r
- if leftParenthesis==-1:\r
- break\r
- key=line[offset:leftParenthesis]\r
- rightParenthesis=line.find(")", leftParenthesis+1)\r
- if rightParenthesis==-1:\r
- raise ValueError("assert")\r
-\r
- param=line[leftParenthesis+1:rightParenthesis]\r
- if key=="shader":\r
- self.shader=int(param)\r
- elif key=="col":\r
- self.color=RGBA(*[float(e) for e in param.split()])\r
- elif key=="dif":\r
- self.diffuse=float(param)\r
- elif key=="amb":\r
- self.ambient=float(param)\r
- elif key=="emi":\r
- self.emit=float(param)\r
- elif key=="spc":\r
- self.specular=float(param)\r
- elif key=="power":\r
- self.power=float(param)\r
- elif key=="tex":\r
- self.tex=param[1:-1]\r
- else:\r
- print(\r
- "%s#parse" % self.name, \r
- "unknown key: %s" % key\r
- )\r
-\r
- offset=rightParenthesis+2\r
-\r
- def __str__(self):\r
- return "<Material %s shader: %d [%f, %f, %f, %f] %f>" % (\r
- self.name, self.shader,\r
- self.color[0], self.color[1], self.color[2], self.color[3],\r
- self.diffuse)\r
-\r
-\r
-class Obj(object):\r
- __slots__=["name", "depth", "folding", \r
- "scale", "rotation", "translation",\r
- "visible", "locking", "shading", "facet",\r
- "color", "color_type", "mirror", "mirror_axis",\r
- "vertices", "faces", "edges", "smoothing",\r
- ]\r
-\r
- def __init__(self, name):\r
- self.name=name\r
- self.vertices=[]\r
- self.faces=[]\r
- self.edges=[]\r
- self.depth=0\r
- self.folding=0\r
- self.scale=[1, 1, 1]\r
- self.rotation=[0, 0, 0]\r
- self.translation=[0, 0, 0]\r
- self.visible=15\r
- self.locking=0\r
- self.shading=0\r
- self.facet=59.5\r
- self.color=[1, 1, 1]\r
- self.color_type=0\r
- self.mirror=0\r
- self.smoothing=0\r
-\r
- def getName(self): return self.name\r
-\r
- def addVertex(self, x, y, z):\r
- self.vertices.append(Vector3(x, y, z))\r
-\r
- def addFace(self, face):\r
- if face.index_count==2:\r
- self.edges.append(face)\r
- else:\r
- self.faces.append(face)\r
-\r
- def __str__(self):\r
- return "<Object %s, %d vertices, %d faces>" % (\r
- self.name, len(self.vertices), len(self.faces))\r
-\r
-\r
-class Face(object):\r
- __slots__=[\r
- "index_count",\r
- "indices", "material_index", "col", "uv",\r
- ]\r
- def __init__(self, index_count, line):\r
- if index_count<2 or index_count>4:\r
- raise ValueError("invalid vertex count: %d" % index_count)\r
- self.material_index=0\r
- self.col=[]\r
- self.uv=[Vector2(0, 0)]*4\r
- self.index_count=index_count\r
- offset=0\r
- while True:\r
- leftParenthesis=line.find("(", offset)\r
- if leftParenthesis==-1:\r
- break\r
- key=line[offset:leftParenthesis]\r
- rightParenthesis=line.find(")", leftParenthesis+1)\r
- if rightParenthesis==-1:\r
- raise ValueError("assert")\r
- params=line[leftParenthesis+1:rightParenthesis].split()\r
- if key=="V":\r
- self.indices=[int(e) for e in params]\r
- elif key=="M":\r
- self.material_index=int(params[0])\r
- elif key=="UV":\r
- uv_list=[float(e) for e in params]\r
- self.uv=[]\r
- for i in range(0, len(uv_list), 2):\r
- self.uv.append(Vector2(uv_list[i], uv_list[i+1]))\r
- elif key=="COL":\r
- for n in params:\r
- d=int(n)\r
- # R\r
- d, m=divmod(d, 256)\r
- self.col.append(m)\r
- # G\r
- d, m=divmod(d, 256)\r
- self.col.append(m)\r
- # B\r
- d, m=divmod(d, 256)\r
- self.col.append(m)\r
- # A\r
- d, m=divmod(d, 256)\r
- self.col.append(m)\r
- else:\r
- print("Face#__init__:unknown key: %s" % key)\r
-\r
- offset=rightParenthesis+2\r
-\r
- def getIndex(self, i): return self.indices[i]\r
- def getUV(self, i): return self.uv[i] if i<len(self.uv) else Vector2(0, 0)\r
-\r
-\r
-def withio(method):\r
- def new(self, path):\r
- self.io=open(path, encoding='cp932')\r
- result=method(self)\r
- self.io=None\r
- return result\r
- return new\r
-\r
-\r
-class IO(object):\r
- __slots__=[\r
- "has_mikoto",\r
- "eof", "io", "lines",\r
- "materials", "objects",\r
- ]\r
- def __init__(self):\r
- self.has_mikoto=False\r
- self.eof=False\r
- self.io=None\r
- self.lines=0\r
- self.materials=[]\r
- self.objects=[]\r
-\r
- def __str__(self):\r
- return "<MQO %d lines, %d materials, %d objects>" % (\r
- self.lines, len(self.materials), len(self.objects))\r
-\r
- def getline(self):\r
- line=self.io.readline()\r
- self.lines+=1\r
- if line=="":\r
- self.eof=True\r
- return None\r
- return line.strip()\r
-\r
- def printError(self, method, msg):\r
- print("%s:%s:%d" % (method, msg, self.lines))\r
-\r
- @withio\r
- def read(self):\r
- line=self.getline()\r
- if line!="Metasequoia Document":\r
- print("invalid signature")\r
- return False\r
-\r
- line=self.getline()\r
- if line!="Format Text Ver 1.0":\r
- print("unknown version: %s" % line)\r
-\r
- while True:\r
- line=self.getline()\r
- if line==None:\r
- # eof\r
- break;\r
- if line=="":\r
- # empty line\r
- continue\r
-\r
- tokens=line.split()\r
- key=tokens[0]\r
-\r
- if key=="Eof":\r
- return True\r
- elif key=="Scene":\r
- if not self.readChunk():\r
- return False\r
- elif key=="Material":\r
- if not self.readMaterial():\r
- return False\r
- elif key=="Object":\r
- firstQuote=line.find('"')\r
- secondQuote=line.find('"', firstQuote+1)\r
- if not self.readObject(line[firstQuote+1:secondQuote]):\r
- return False\r
- elif key=="BackImage":\r
- if not self.readChunk():\r
- return False\r
- elif key=="IncludeXml":\r
- firstQuote=line.find('"')\r
- secondQuote=line.find('"', firstQuote+1)\r
- print("IncludeXml", line[firstQuote+1:secondQuote])\r
- else:\r
- print("unknown key: %s" % key)\r
- if not self.readChunk():\r
- return False\r
-\r
- self.printError("parse", "invalid eof")\r
- return False\r
-\r
- def readObject(self, name):\r
- obj=Obj(name)\r
- if name.startswith('bone'):\r
- self.has_mikoto=True\r
- self.objects.append(obj)\r
- while(True):\r
- line=self.getline()\r
- if line==None:\r
- # eof\r
- break;\r
- if line=="":\r
- # empty line\r
- continue\r
-\r
- if line=="}":\r
- return True\r
- else:\r
- tokens=line.split()\r
- key=tokens[0]\r
- if key=="vertex":\r
- if not self.readVertex(obj):\r
- return False\r
- elif key=="face":\r
- if not self.readFace(obj):\r
- return False\r
- elif key=="depth":\r
- obj.depth=int(tokens[1])\r
- else:\r
- print(\r
- "%s#readObject" % name,\r
- "unknown key: %s" % name\r
- )\r
-\r
- self.printError("readObject", "invalid eof")\r
- return False\r
-\r
- def readFace(self, obj):\r
- while(True):\r
- line=self.getline()\r
- if line==None:\r
- # eof\r
- break;\r
- if line=="":\r
- # empty line\r
- continue\r
-\r
- if line=="}":\r
- return True\r
- else:\r
- # face\r
- tokens=line.split(' ', 1)\r
- try:\r
- obj.addFace(Face(int(tokens[0]), tokens[1]))\r
- except ValueError as ex:\r
- self.printError("readFace", ex)\r
- #return False\r
-\r
- self.printError("readFace", "invalid eof")\r
- return False\r
-\r
- def readVertex(self, obj):\r
- while(True):\r
- line=self.getline()\r
- if line==None:\r
- # eof\r
- break;\r
- if line=="":\r
- # empty line\r
- continue\r
-\r
- if line=="}":\r
- return True\r
- else:\r
- # vertex\r
- obj.addVertex(*[float(v) for v in line.split()])\r
-\r
- self.printError("readVertex", "invalid eof")\r
- return False\r
-\r
- def readMaterial(self):\r
- while(True):\r
- line=self.getline()\r
- if line==None:\r
- # eof\r
- break;\r
- if line=="":\r
- # empty line\r
- continue\r
-\r
- if line=="}":\r
- return True\r
- else:\r
- # material\r
- secondQuaote=line.find('"', 1) \r
- material=Material(line[1:secondQuaote])\r
- try:\r
- material.parse(line[secondQuaote+2:])\r
- except ValueError as ex:\r
- self.printError("readMaterial", ex)\r
-\r
- self.materials.append(material)\r
-\r
- self.printError("readMaterial", "invalid eof")\r
- return False\r
-\r
- def readChunk(self):\r
- level=1\r
- while(True):\r
- line=self.getline()\r
- if line==None:\r
- # eof\r
- break;\r
- if line=="":\r
- # empty line\r
- continue\r
-\r
- if line=="}":\r
- level-=1\r
- if level==0:\r
- return True\r
- elif line.find("{")!=-1:\r
- level+=1\r
-\r
- self.printError("readChunk", "invalid eof")\r
- return False\r
-\r
+++ /dev/null
-# coding: utf-8
-
-#from distutils.core import setup, Extension
-from setuptools import setup, Extension
-import os
-import sys
-import shutil
-
-VERSION='1.03'
-
-option={
- 'swig_opts': ['-c++'],
- 'include_dirs': [
- '../include'
- ],
- 'libraries': [
- 'meshio',
- ],
- 'library_dirs': [
- '../release',
- ],
- }
-
-# copy englishmap
-shutil.copy("pymeshio/englishmap.py", ".")
-
-if os.name=='nt':
- # vc option
- option['extra_compile_args']=[
- '/EHsc', '/MT',
- ]
-
-# swig c extensions
-ext_modules=[
- Extension("_mqo", ["mqo.i"], **option),
- Extension("_pmd", ["pmd.i"], **option),
- Extension("_vmd", ["vmd.i"], **option),
- ]
-
-# blender importers
-if sys.version_info[0]<3:
- # blender 2.4
- data_files=[
- ('blender24', [
- 'blender/README24',
- 'blender/bl24.py',
- 'blender/mqo_import.py',
- 'blender/mqo_export.py',
- 'blender/pmd_import.py',
- 'blender/pmd_export.py',
- ]),
- ('blender24/pymeshio', [
- 'pymeshio/__init__.py',
- 'pymeshio/mqo.py',
- 'pymeshio/mmd.py',
- 'pymeshio/englishmap.py',
- ]),
- ]
-
-else:
- # rename blender25 files
- if not os.path.exists("addons"):
- os.mkdir("addons")
- shutil.copy("blender/mqo_import.py", "addons/io_import_scene_mqo.py")
- shutil.copy("blender/mqo_export.py", "addons/io_export_scene_mqo.py")
- shutil.copy("blender/pmd_import.py", "addons/io_import_scene_pmd.py")
- shutil.copy("blender/pmd_export.py", "addons/io_export_scene_pmd.py")
-
- # blender2.5
- data_files=[
- ('blender25', [
- 'blender/README25',
- ]),
- ('blender25/addons', [
- 'blender/bl25.py',
- 'addons/io_import_scene_mqo.py',
- 'addons/io_export_scene_mqo.py',
- 'addons/io_import_scene_pmd.py',
- 'addons/io_export_scene_pmd.py',
- ]),
- ('blender25/addons/pymeshio', [
- 'pymeshio/__init__.py',
- 'pymeshio/mqo.py',
- 'pymeshio/mmd.py',
- 'pymeshio/englishmap.py',
- ]),
- ]
-
-if os.name=='nt':
- import distutils.msvc9compiler
- org=distutils.msvc9compiler.MSVCCompiler.link
- def custom(self, *args):
- try:
- org(self, *args)
- except distutils.msvc9compiler.LinkError as e:
- print(e)
- distutils.msvc9compiler.MSVCCompiler.link=custom
-
-else:
- import re
- pattern=re.compile("<:")
- def edit(f):
- new_file=f+".cpp"
- io=open(new_file, 'wb')
- for line in open(f):
- if sys.version_info[0]<3:
- io.write(pattern.sub("< :", line))
- else:
- io.write(pattern.sub("< :", line).encode('utf-8'))
- io.close()
- return new_file
-
- import distutils.command.build_ext
- org=distutils.command.build_ext.build_ext.swig_sources
- def custom(self, sources, extension):
- return [edit(f) for f in org(self, sources, extension)]
- distutils.command.build_ext.build_ext.swig_sources=custom
-
-setup(name="meshio",
- version=VERSION,
- description='polygon mesh io utilities',
- author='ousttrue',
- author_email='ousttrue@gmail.com',
- url='http://sourceforge.jp/projects/meshio/',
- packages=['meshio'],
- package_dir={'meshio': '.'},
- ext_package='meshio',
- #ext_modules=ext_modules,
- data_files=data_files,
- classifiers = [
- "Programming Language :: Python",
- "Programming Language :: Python :: 3",
- "Development Status :: 4 - Beta",
- "Environment :: Other Environment",
- "Intended Audience :: Developers",
- "License :: OSI Approved :: BSD License",
- "Operating System :: Microsoft :: Windows",
- "Operating System :: POSIX :: Linux",
- "Natural Language :: Japanese",
- "Topic :: Multimedia :: Graphics :: 3D Modeling",
- ],
- )
-
+++ /dev/null
-%module vmd
-%{
-#include <vmd.h>
-using namespace meshio;
-using namespace vmd;
-%}
-%include "std_wstring.i"
-%include "std_vector.i"
-%include "std_map.i"
-%include "../include/vmd.h"
-%include "../include/color.h"
-%include "../include/la.h"
-
-%template(BoneKeyFrame) meshio::vmd::KeyFrame<meshio::vmd::BoneKey>;
-%template(BoneKeyFrameVector) std::vector<meshio::vmd::KeyFrame<meshio::vmd::BoneKey> >;
-%template(BoneKeyFrameList) meshio::vmd::KeyFrameList<meshio::vmd::KeyFrame<meshio::vmd::BoneKey> >;
-
-%template(MorphKeyFrame) meshio::vmd::KeyFrame<meshio::vmd::MorphKey>;
-%template(MorphKeyFrameVector) std::vector<meshio::vmd::KeyFrame<meshio::vmd::MorphKey> >;
-%template(MorphKeyFrameList) meshio::vmd::KeyFrameList<meshio::vmd::KeyFrame<meshio::vmd::MorphKey> >;
-
-%template(WStringVector) std::vector<std::wstring>;
-