Table Of Contents

Previous topic

BVHローダ

Next topic

ボーンの頂点配列化とスケルトンクラスの分離

This Page

BVHモーション再生

BVHモーションから読み込んだボーンをアニメーションさせる。

BVH.py

#!/usr/bin/python
# coding: utf-8

from OpenGL.GL import *
from OpenGL.GLU import *
import numpy


class BVH(object):
    def __init__(self, root, frame_interval, frame_count):
        """
        root: root joint
        frame_interval: mili sec in a frame
        frame_count: total frame count
        """
        # アニメショーン経過時間
        self.elaps=0
        # 再生中のフレーム
        self.currentFrame=0
        # 停止フラグ
        self.pause=False
        # バインドポーズフラグ
        self.bind=False

        self.root=root
        # sec -> msec
        self.frame_interval=frame_interval
        self.frame_count=frame_count
        
    def onUpdate(self, interval):
        if not self.pause:
            self.elaps+=interval
            self.currentFrame=int(self.elaps/self.frame_interval) % self.frame_count
    def onKeyDown(self, key):
        if key==' ':
            self.toggle()
        elif key=='n':
            self.advanceFrame(1)
        elif key=='p':
            self.advanceFrame(-1)
        elif key=='r':
            self.setFrame(0)
        elif key=='b':
            self.toggleBind()

    def draw(self):
        glColor(1, 1, 1, 1)
        if self.root:
            self.drawJoint(self.root)

    def drawJoint(self, joint):
        glPushMatrix()

        glMultMatrixf(
                numpy.dot(
                    joint.getMatrix(self.currentFrame), 
                    joint.getOffsetMatrix()))

        glColor3ub(255, 0, 0)
        glPointSize(5)
        glBegin(GL_POINTS)
        glVertex(0, 0, 0)
        glEnd()

        for child in joint.children:
            glColor3ub(255, 255, 255)
            glBegin(GL_LINES)
            glVertex(0, 0, 0)
            glVertex(child.offset)
            glEnd()

            self.drawJoint(child)
        glPopMatrix()

    def toggle(self):
        self.pause=not self.pause

    def advanceFrame(self, d):
        self.currentFrame+=d
        if self.currentFrame<0:
            self.currentFrame=0
        if self.currentFrame>=self.frame_count:
            self.frame_count-1

    def setFrame(self, frame):
        self.currentFrame=frame
        if self.currentFrame<0:
            self.currentFrame=0
        if self.currentFrame>=self.frame_count:
            self.frame_count-1

    def toggleBind(self):
        self.bind=not self.bind


if __name__=="__main__":
    import sys
    import glbase
    import pg_ui
    import Rokuro
    import bvhloader

    if len(sys.argv)<2:
        print "usage: %s {bvh file}" % sys.argv[0]
        sys.exit()

    l=bvhloader.load(sys.argv[1])
    if not l:
        print "fail to load", sys.argv[1]
        sys.exit()
    print l

    pg_ui.run(glbase.BaseController(Rokuro.RokuroView(100), 
        BVH(l.root, l.frame_interval*1000, l.frame_count)))

タイマーから取得した経過時間(ミリ秒)をフレームに換算して、 各チャンネルの対応する値を得る。また、各ジョイントは、保持するチャンネルの値を合成して4x4の行列を生成する。

この行列が各ジョイントのそのフレームでの姿勢をあらわす。

Rootジョイントからの再帰的な描画

    def drawJoint(self, joint):
        glPushMatrix()

        glMultMatrixf(
                numpy.dot(
                    joint.getMatrix(self.currentFrame), 
                    joint.getOffsetMatrix()))

        glColor3ub(255, 0, 0)
        glPointSize(5)
        glBegin(GL_POINTS)
        glVertex(0, 0, 0)
        glEnd()

        for child in joint.children:
            glColor3ub(255, 255, 255)
            glBegin(GL_LINES)
            glVertex(0, 0, 0)
            glVertex(child.offset)
            glEnd()

            self.drawJoint(child)
        glPopMatrix()
inserted by FC2 system