OSDN Git Service

add mqo loader
authorousttrue <ousttrue@gmail.com>
Wed, 28 Sep 2011 02:32:12 +0000 (11:32 +0900)
committerousttrue <ousttrue@gmail.com>
Wed, 28 Sep 2011 02:32:12 +0000 (11:32 +0900)
.gitignore
examples/cube.mqo [new file with mode: 0644]
examples/front.jpg [new file with mode: 0644]
examples/material.py [new file with mode: 0644]
examples/mqobuilder.py [new file with mode: 0644]
examples/opengl/__init__.py
examples/pymeshviewer.py
examples/texture.py [new file with mode: 0644]
examples/vertexarray.py [new file with mode: 0644]
examples/vertexarraymap.py [new file with mode: 0644]

index cfe6115..3687164 100644 (file)
@@ -2,3 +2,4 @@ Makefile
 build
 dist
 pymeshio.egg-info
+*.pyc
diff --git a/examples/cube.mqo b/examples/cube.mqo
new file mode 100644 (file)
index 0000000..e56de65
--- /dev/null
@@ -0,0 +1,52 @@
+Metasequoia Document\r
+Format Text Ver 1.0\r
+\r
+Scene {\r
+       pos 48.0899 60.6742 2400.0000\r
+       lookat 0.0000 0.0000 0.0000\r
+       head 0.0000\r
+       pich 0.0000\r
+       ortho 1\r
+       zoom2 3.1250\r
+       amb 0.250 0.250 0.250\r
+}\r
+Material 6 {\r
+       "mat1" shader(3) col(1.000 0.000 0.000 1.000) dif(0.800) amb(0.600) emi(0.000) spc(0.000) power(5.00)\r
+       "mat2" shader(3) col(0.000 0.000 1.000 1.000) dif(0.800) amb(0.600) emi(0.000) spc(0.000) power(5.00) tex("front.jpg")\r
+       "mat3" shader(3) col(1.000 1.000 0.000 1.000) dif(0.800) amb(0.600) emi(0.000) spc(0.000) power(5.00)\r
+       "mat4" shader(3) col(0.000 0.749 0.169 1.000) dif(0.800) amb(0.600) emi(0.000) spc(0.000) power(5.00)\r
+       "mat5" shader(3) col(1.000 1.000 1.000 1.000) dif(0.800) amb(0.600) emi(0.000) spc(0.000) power(5.00)\r
+       "mat6" shader(3) col(1.000 0.000 1.000 1.000) dif(0.800) amb(0.600) emi(0.000) spc(0.000) power(5.00)\r
+}\r
+Object "obj1" {\r
+       depth 0\r
+       folding 0\r
+       scale 1.000000 1.000000 1.000000\r
+       rotation 0.000000 0.000000 0.000000\r
+       translation 0.000000 0.000000 0.000000\r
+       visible 15\r
+       locking 0\r
+       shading 1\r
+       facet 59.5\r
+       color 0.898 0.498 0.698\r
+       color_type 0\r
+       vertex 8 {\r
+               -100.0000 100.0000 100.0000\r
+               -100.0000 -100.0000 100.0000\r
+               100.0000 100.0000 100.0000\r
+               100.0000 -100.0000 100.0000\r
+               100.0000 100.0000 -100.0000\r
+               100.0000 -100.0000 -100.0000\r
+               -100.0000 100.0000 -100.0000\r
+               -100.0000 -100.0000 -100.0000\r
+       }\r
+       face 6 {\r
+               4 V(0 2 3 1) M(1) UV(0.00000 0.00000 1.00000 0.00000 1.00000 1.00000 0.00000 1.00000)\r
+               4 V(2 4 5 3) M(0) UV(0.00000 0.00000 1.00000 0.00000 1.00000 1.00000 0.00000 1.00000)\r
+               4 V(4 6 7 5) M(2) UV(0.00000 0.00000 1.00000 0.00000 1.00000 1.00000 0.00000 1.00000)\r
+               4 V(6 0 1 7) M(3) UV(0.00000 0.00000 1.00000 0.00000 1.00000 1.00000 0.00000 1.00000)\r
+               4 V(6 4 2 0) M(4) UV(0.00000 0.00000 1.00000 0.00000 1.00000 1.00000 0.00000 1.00000)\r
+               4 V(1 3 5 7) M(5) UV(0.00000 0.00000 1.00000 0.00000 1.00000 1.00000 0.00000 1.00000)\r
+       }\r
+}\r
+Eof\r
diff --git a/examples/front.jpg b/examples/front.jpg
new file mode 100644 (file)
index 0000000..19bb34e
Binary files /dev/null and b/examples/front.jpg differ
diff --git a/examples/material.py b/examples/material.py
new file mode 100644 (file)
index 0000000..7b9c0cb
--- /dev/null
@@ -0,0 +1,72 @@
+#!/usr/bin/pyhthon
+# coding: utf-8
+
+from OpenGL.GL import *
+import texture
+
+'''
+Material
+
+* 色
+'''
+class Material(object):
+    def __init__(self, r, g, b, a):
+        self.r=r
+        self.g=g
+        self.b=b
+        self.a=a
+
+    def begin(self):
+        glColor4f(self.r, self.g, self.b, self.a)
+
+    def end(self):
+        pass
+
+    def onInitialize(self):
+        pass
+
+    @staticmethod
+    def create(src):
+        m=material.Material(*src.col)
+        return m
+
+
+'''
+Material
+
+* 色
+* テクスチャー
+'''
+class MQOMaterial(object):
+    def __init__(self, rgba):
+        self.rgba=rgba
+        self.texture=None
+
+    def begin(self):
+        glColor4f(self.rgba.r, self.rgba.g, self.rgba.b, self.rgba.a)
+        if self.texture:
+            self.texture.begin()
+
+        # backface culling
+        glEnable(GL_CULL_FACE)
+        glFrontFace(GL_CW)
+        glCullFace(GL_BACK)
+        # alpha test
+        glEnable(GL_ALPHA_TEST);
+        glAlphaFunc(GL_GREATER, 0.5);
+
+    def end(self):
+        if self.texture:
+            self.texture.end()
+
+    def onInitialize(self):
+        if self.texture:
+            self.texture.onInitialize()
+
+    @staticmethod
+    def create(src, basedir):
+        m=MQOMaterial(src.color)
+        if src.tex:
+            m.texture=texture.Texture((basedir+'/'+src.tex).replace('\\', '/'))
+        return m
+
diff --git a/examples/mqobuilder.py b/examples/mqobuilder.py
new file mode 100644 (file)
index 0000000..b454b39
--- /dev/null
@@ -0,0 +1,61 @@
+#!/usr/bin/env python\r
+# coding: utf-8\r
+\r
+import time\r
+import os\r
+import pymeshio.mqo\r
+import material\r
+import vertexarraymap\r
+\r
+\r
+def build(path):\r
+    # load scenee\r
+    t=time.time()\r
+    io=pymeshio.mqo.IO()\r
+    if not io.read(path):\r
+        return\r
+    print(time.time()-t, "sec")\r
+    # build\r
+    basedir=os.path.dirname(path)\r
+    vertexArrayMap=vertexarraymap.VertexArrayMapWithUV(\r
+            [material.MQOMaterial.create(m, basedir) \r
+                for m in io.materials])\r
+    for o in io.objects:\r
+        # skip mikoto objects\r
+        if o.name.startswith("anchor"):\r
+            continue\r
+        if o.name.startswith("bone:"):\r
+            continue\r
+        if o.name.startswith("MCS:"):\r
+            continue\r
+\r
+        for f in o.faces:\r
+            if f.index_count==3:\r
+                vertexArrayMap.addTriangle(\r
+                        f.material_index,\r
+                        o.vertices[f.indices[0]],\r
+                        o.vertices[f.indices[1]],\r
+                        o.vertices[f.indices[2]],\r
+                        f.uv[0], f.uv[1], f.uv[2]\r
+                        )\r
+            elif f.index_count==4:\r
+                # triangle 1\r
+                vertexArrayMap.addTriangle(\r
+                        f.material_index,\r
+                        o.vertices[f.indices[0]],\r
+                        o.vertices[f.indices[1]],\r
+                        o.vertices[f.indices[2]],\r
+                        f.uv[0], f.uv[1], f.uv[2]\r
+                        )\r
+                # triangle 2\r
+                vertexArrayMap.addTriangle(\r
+                        f.material_index,\r
+                        o.vertices[f.indices[2]],\r
+                        o.vertices[f.indices[3]],\r
+                        o.vertices[f.indices[0]],\r
+                        f.uv[2], f.uv[3], f.uv[0]\r
+                        )\r
+\r
+    vertexArrayMap.optimize()\r
+    return vertexArrayMap\r
+\r
index 75c50a2..dfbf712 100644 (file)
@@ -9,12 +9,19 @@ from .baseview import *
 DELEGATE_PATTERN=re.compile('^on[A-Z]')\r
 \r
 class BaseController(object):\r
-    def __init__(self, view, root):\r
-        self.view=view\r
+    def __init__(self, view):\r
+        self.isInitialized=False\r
+        self.setView(view)\r
+        self.root=None\r
+\r
+    def setRoot(self, root):\r
         self.root=root\r
+        self.delegate(root)\r
         self.isInitialized=False\r
+\r
+    def setView(self, view):\r
+        self.view=view\r
         self.delegate(view)\r
-        self.delegate(root)\r
 \r
     def delegate(self, to):\r
         for name in dir(to):  \r
@@ -56,6 +63,7 @@ class BaseController(object):
         glLoadIdentity()\r
         # OpenGL\95`\89æ\r
         self.view.updateView()\r
-        self.root.draw()\r
+        if self.root:\r
+            self.root.draw()\r
         glFlush()\r
 \r
index 2063c8e..25927b8 100644 (file)
@@ -2,12 +2,13 @@
 # coding: utf-8\r
 \r
 import sys\r
+import os\r
 import tkinter\r
 import tkinter.filedialog\r
 import togl\r
 import opengl\r
 import opengl.rokuro\r
-import triangle\r
+import mqobuilder\r
 \r
 \r
 class Frame(tkinter.Frame):\r
@@ -20,18 +21,18 @@ class Frame(tkinter.Frame):
         self.master.config(menu=menu_bar)\r
 \r
         menu_file = tkinter.Menu(menu_bar, tearoff=False)\r
-        menu_bar.add_cascade(label='FILE', menu=menu_file, underline=0)\r
+        menu_bar.add_cascade(label='File', menu=menu_file, underline=0)\r
 \r
         menu_file.add_command(label='Open', under=0, command=self.onOpen)\r
 \r
         # setup opengl widget\r
-        self.glworld=opengl.BaseController(opengl.rokuro.RokuroView(25), triangle.Triangle(5))\r
-        glwidget=togl.Widget(self, self.glworld, width=width, height=height)\r
-        glwidget.pack(fill=tkinter.BOTH, expand=True)\r
+        self.glworld=opengl.BaseController(opengl.rokuro.RokuroView(25))\r
+        self.glwidget=togl.Widget(self, self.glworld, width=width, height=height)\r
+        self.glwidget.pack(fill=tkinter.BOTH, expand=True)\r
 \r
         # event binding\r
         self.bind('<Key>', self.onKeyDown)\r
-        self.bind('<MouseWheel>', lambda e: self.glworld.onWheel(-e.delta) and glwidget.onDraw())\r
+        self.bind('<MouseWheel>', lambda e: self.glworld.onWheel(-e.delta) and self.glwidget.onDraw())\r
 \r
     def onOpen(self):\r
         filename=tkinter.filedialog.askopenfilename(\r
@@ -39,7 +40,24 @@ class Frame(tkinter.Frame):
                     ('poloygon model files', '*.mqo;*.pmd'),\r
                     ], \r
                 initialdir=self.current)\r
-        print('open: %s' % filename)\r
+        if filename.lower().endswith(".mqo"):\r
+            self.loadMqo(filename)\r
+        elif filename.lower().endswith(".pmd"):\r
+            self.loadPmd(filename)\r
+        self.current=os.path.dirname(filename)\r
+\r
+    def loadMqo(self, path):\r
+        # load scenee\r
+        model=mqobuilder.build(path)\r
+        if not model:\r
+            print('fail to load %s' % path)\r
+            return\r
+        self.glworld.setRoot(model)\r
+        print('loadMqo %s' % path)\r
+        self.glwidget.onDraw()\r
+\r
+    def loadPmd(self, path):\r
+        print('loadPmd %s' % path)\r
 \r
     def onKeyDown(self, event):\r
         key=event.keycode\r
diff --git a/examples/texture.py b/examples/texture.py
new file mode 100644 (file)
index 0000000..548e423
--- /dev/null
@@ -0,0 +1,62 @@
+#!/usr/bin/python
+# coding: utf-8
+
+from PIL import Image
+from OpenGL.GL import *
+
+
+class Texture(object):
+
+    def __init__(self, path):
+        self.path=path
+        self.image=None
+
+    def onInitialize(self):
+        if not self.image:
+            self.loadImage()
+
+        assert(self.image)
+        if self.createTexture():
+            return True
+
+    def loadImage(self):
+        self.image=Image.open(self.path)
+        if self.image:
+            print("load image:", self.path)
+            return True
+        else:
+            print("failt to load image:", self.path)
+            return False
+
+    def createTexture(self):
+        self.texture=glGenTextures(1)
+        if self.texture==0:
+            print("fail to glGenTextures")
+            return False
+
+        channels=len(self.image.getbands())
+        w, h=self.image.size
+        glBindTexture(GL_TEXTURE_2D, self.texture)
+        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP)
+        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP)
+        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
+        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
+        if channels==4:
+            print("RGBA")
+            glPixelStorei(GL_UNPACK_ALIGNMENT, 4)
+            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 
+                    0, GL_RGBA, GL_UNSIGNED_BYTE, self.image.tostring())
+        elif channels==3:
+            print("RGB")
+            glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
+            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 
+                    0, GL_RGB, GL_UNSIGNED_BYTE, self.image.tostring())
+
+    def begin(self):
+        glEnable(GL_TEXTURE_2D)
+        glBindTexture(GL_TEXTURE_2D, self.texture)
+
+    def end(self):
+        glDisable(GL_TEXTURE_2D)
+
+
diff --git a/examples/vertexarray.py b/examples/vertexarray.py
new file mode 100644 (file)
index 0000000..749b6e0
--- /dev/null
@@ -0,0 +1,116 @@
+#!/usr/bin/python\r
+# coding: utf-8\r
+\r
+from OpenGL.GL import *\r
+\r
+'''\r
+頂点配列\r
+\r
+====\r
+属性\r
+====\r
+* 位置\r
+'''\r
+class VertexArray(object):\r
+    def __init__(self, vertices):\r
+        self.vertices=vertices\r
+\r
+    def __str__(self):\r
+        return "<VertexArray %d>" % len(self.vertices)\r
+\r
+    def draw(self):\r
+        # 位置属性\r
+        glEnableClientState(GL_VERTEX_ARRAY)\r
+        glVertexPointer(3, GL_FLOAT, 0, self.vertices)\r
+        # 描画\r
+        glDrawArrays(GL_TRIANGLES, 0, len(self.vertices))\r
+        # 後始末\r
+        glDisableClientState(GL_VERTEX_ARRAY)\r
+\r
+\r
+\r
+'''\r
+頂点配列\r
+\r
+====\r
+属性\r
+====\r
+* 位置\r
+* UV\r
+'''\r
+class VertexArrayWithUV(object):\r
+    def __init__(self, vertices, uvarray):\r
+        self.vertices=vertices\r
+        self.uvarray=uvarray\r
+\r
+    def __str__(self):\r
+        return "<VertexArrayWithUV %d>" % len(self.vertices)\r
+\r
+    def draw(self):\r
+        # 位置属性\r
+        glEnableClientState(GL_VERTEX_ARRAY)\r
+        glVertexPointer(3, GL_FLOAT, 0, self.vertices)\r
+        # UV属性\r
+        glEnableClientState(GL_TEXTURE_COORD_ARRAY)\r
+        glTexCoordPointer(2, GL_FLOAT, 0, self.uvarray)\r
+        # 描画\r
+        triangle_count=int(len(self.vertices)/3)\r
+        glDrawArrays(GL_TRIANGLES, 0, triangle_count)\r
+        # 後始末\r
+        glDisableClientState(GL_TEXTURE_COORD_ARRAY)\r
+        glDisableClientState(GL_VERTEX_ARRAY)\r
+\r
+\r
+'''\r
+インデックス参照頂点配列\r
+\r
+====\r
+属性\r
+====\r
+* 位置\r
+'''\r
+class IndexedVertexArray(object):\r
+    def __init__(self, vertices, indices):\r
+        self.vertices=vertices\r
+        self.indices=indices\r
+\r
+    def draw(self):\r
+        # 位置属性\r
+        glEnableClientState(GL_VERTEX_ARRAY)\r
+        glVertexPointer(3, GL_FLOAT, 0, self.vertices)\r
+        # indexによる描画\r
+        glDrawElements(GL_TRIANGLES, len(self.indices),\r
+                GL_UNSIGNED_INT, self.indices)\r
+        # 後始末\r
+        glDisableClientState(GL_VERTEX_ARRAY)\r
+\r
+\r
+'''\r
+インデックス参照頂点配列\r
+\r
+====\r
+属性\r
+====\r
+* 位置\r
+* 色\r
+'''\r
+class IndexedVertexArrayWithColor(object):\r
+    def __init__(self, vertices, colors, indices):\r
+        self.vertices=vertices\r
+        self.colors=colors\r
+        self.indices=indices\r
+\r
+    def draw(self):\r
+        # 位置属性\r
+        glEnableClientState(GL_VERTEX_ARRAY)\r
+        glVertexPointer(3, GL_FLOAT, 0, self.vertices)\r
+        # 色属性\r
+        glEnableClientState(GL_COLOR_ARRAY)\r
+        glColorPointer(3, GL_FLOAT, 0, self.colors)\r
+        # indexによる描画\r
+        glDrawElements(GL_TRIANGLES, len(self.indices),\r
+                GL_UNSIGNED_INT, self.indices)\r
+        # 後始末\r
+        glDisableClientState(GL_COLOR_ARRAY)\r
+        glDisableClientState(GL_VERTEX_ARRAY)\r
+\r
diff --git a/examples/vertexarraymap.py b/examples/vertexarraymap.py
new file mode 100644 (file)
index 0000000..6994483
--- /dev/null
@@ -0,0 +1,92 @@
+#!/usr/bin/python
+# coding: utf-8
+
+import numpy
+import vertexarray
+
+
+'''
+頂点配列をマテリアル毎に分別する
+'''
+class VertexArrayMap(object):
+    def __init__(self, materials):
+        self.materials=materials
+        self.vertexArrayMap={}
+
+    def getVertexArray(self, material_index):
+        material=self.materials[material_index]
+        if not material in self.vertexArrayMap:
+            vertexArray=vertexarray.VertexArray([])
+            self.vertexArrayMap[material]=vertexArray
+        return self.vertexArrayMap[material]
+
+    def addTriangle(self, material_index, v0, v1, v2):
+        vertexArray=self.getVertexArray(material_index)
+        vertexArray.vertices.append(v0.x)
+        vertexArray.vertices.append(v0.y)
+        vertexArray.vertices.append(v0.z)
+        vertexArray.vertices.append(v1.x)
+        vertexArray.vertices.append(v1.y)
+        vertexArray.vertices.append(v1.z)
+        vertexArray.vertices.append(v2.x)
+        vertexArray.vertices.append(v2.y)
+        vertexArray.vertices.append(v2.z)
+
+    def draw(self):
+        for m, vertexArray in self.vertexArrayMap.items():
+            m.begin()
+            vertexArray.draw()
+            m.end()
+
+    def optimize(self):
+        for v in self.vertexArrayMap.values():
+            v.vertices=numpy.array(v.vertices, 'f') 
+
+
+'''
+頂点配列をマテリアル毎に分別する(UV付き)
+'''
+class VertexArrayMapWithUV(object):
+    def __init__(self, materials):
+        self.materials=materials
+        self.vertexArrayWithUVMap={}
+
+    def getVertexArray(self, material_index):
+        material=self.materials[material_index]
+        if not material in self.vertexArrayWithUVMap:
+            vertexArray=vertexarray.VertexArrayWithUV([], [])
+            self.vertexArrayWithUVMap[material]=vertexArray
+        return self.vertexArrayWithUVMap[material]
+
+    def addTriangle(self, material_index, v0, v1, v2, uv0, uv1, uv2):
+        vertexArray=self.getVertexArray(material_index)
+        vertexArray.vertices.append(v0.x)
+        vertexArray.vertices.append(v0.y)
+        vertexArray.vertices.append(v0.z)
+        vertexArray.vertices.append(v1.x)
+        vertexArray.vertices.append(v1.y)
+        vertexArray.vertices.append(v1.z)
+        vertexArray.vertices.append(v2.x)
+        vertexArray.vertices.append(v2.y)
+        vertexArray.vertices.append(v2.z)
+        vertexArray.uvarray.append(uv0.x)
+        vertexArray.uvarray.append(uv0.y)
+        vertexArray.uvarray.append(uv1.x)
+        vertexArray.uvarray.append(uv1.y)
+        vertexArray.uvarray.append(uv2.x)
+        vertexArray.uvarray.append(uv2.y)
+
+    def draw(self):
+        for m, vertexArray in self.vertexArrayWithUVMap.items():
+            m.begin()
+            vertexArray.draw()
+            m.end()
+
+    def optimize(self):
+        for v in self.vertexArrayWithUVMap.values():
+            v.vertices=numpy.array(v.vertices, 'f') 
+            v.uvarray=numpy.array(v.uvarray, 'f') 
+
+    def onInitialize(self):
+        [m.onInitialize() for m in self.materials]
+