BVHモーションから読み込んだボーンをアニメーションさせる。
#!/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の行列を生成する。
この行列が各ジョイントのそのフレームでの姿勢をあらわす。
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()