home *** CD-ROM | disk | FTP | other *** search
- # ***** BEGIN LICENSE BLOCK *****
- # Version: MPL 1.1/GPL 2.0/LGPL 2.1
- #
- # The contents of this file are subject to the Mozilla Public License Version
- # 1.1 (the "License"); you may not use this file except in compliance with
- # the License. You may obtain a copy of the License at
- # http://www.mozilla.org/MPL/
- #
- # Software distributed under the License is distributed on an "AS IS" basis,
- # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- # for the specific language governing rights and limitations under the
- # License.
- #
- # The Original Code is the Python Computer Graphics Kit.
- #
- # The Initial Developer of the Original Code is Matthias Baas.
- # Portions created by the Initial Developer are Copyright (C) 2004
- # the Initial Developer. All Rights Reserved.
- #
- # Contributor(s):
- #
- # Alternatively, the contents of this file may be used under the terms of
- # either the GNU General Public License Version 2 or later (the "GPL"), or
- # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- # in which case the provisions of the GPL or the LGPL are applicable instead
- # of those above. If you wish to allow use of your version of this file only
- # under the terms of either the GPL or the LGPL, and not to allow others to
- # use your version of this file under the terms of the MPL, indicate your
- # decision by deleting the provisions above and replace them with the notice
- # and other provisions required by the GPL or the LGPL. If you do not delete
- # the provisions above, a recipient may use your version of this file under
- # the terms of any one of the MPL, the GPL or the LGPL.
- #
- # ***** END LICENSE BLOCK *****
- # $Id: bvh.py,v 1.1 2005/02/06 22:26:02 mbaas Exp $
-
- ## \file bvh.py
- ## Contains the BVHReader class.
-
- import string
-
- # Node
- class Node:
- def __init__(self, root=False):
- self.name = None
- self.channels = []
- self.offset = (0,0,0)
- self.children = []
- self._is_root = root
-
- def isRoot(self):
- return self._is_root
-
- def isEndSite(self):
- return len(self.children)==0
-
-
- # BVHReader
- class BVHReader:
- """Read BioVision Hierarchical (BVH) files.
- """
-
- def __init__(self, filename):
-
- self.filename = filename
- # A list of unprocessed tokens (strings)
- self.tokenlist = []
- # The current line number
- self.linenr = 0
-
- # Root node
- self._root = None
- self._nodestack = []
-
- # Total number of channels
- self._numchannels = 0
-
- def onHierarchy(self, root):
- pass
-
- def onMotion(self, frames, dt):
- pass
-
- def onFrame(self, values):
- pass
-
- # read
- def read(self):
- """Read the entire file.
- """
- self.fhandle = file(self.filename)
-
- self.readHierarchy()
- self.onHierarchy(self._root)
- self.readMotion()
-
- # readMotion
- def readMotion(self):
- """Read the motion samples.
- """
- # No more tokens (i.e. end of file)? Then just return
- try:
- tok = self.token()
- except StopIteration:
- return
-
- if tok!="MOTION":
- raise SyntaxError, "Syntax error in line %d: 'MOTION' expected, got '%s' instead"%(self.linenr, tok)
-
- # Read the number of frames
- tok = self.token()
- if tok!="Frames:":
- raise SyntaxError, "Syntax error in line %d: 'Frames:' expected, got '%s' instead"%(self.linenr, tok)
-
- frames = self.intToken()
-
- # Read the frame time
- tok = self.token()
- if tok!="Frame":
- raise SyntaxError, "Syntax error in line %d: 'Frame Time:' expected, got '%s' instead"%(self.linenr, tok)
- tok = self.token()
- if tok!="Time:":
- raise SyntaxError, "Syntax error in line %d: 'Frame Time:' expected, got 'Frame %s' instead"%(self.linenr, tok)
-
- dt = self.floatToken()
-
- self.onMotion(frames, dt)
-
- # Read the channel values
- for i in range(frames):
- s = self.readLine()
- a = s.split()
- if len(a)!=self._numchannels:
- raise SyntaxError, "Syntax error in line %d: %d float values expected, got %d instead"%(self.linenr, self._numchannels, len(a))
- values = map(lambda x: float(x), a)
- self.onFrame(values)
-
-
- # readHierarchy
- def readHierarchy(self):
- """Read the skeleton hierarchy.
- """
- tok = self.token()
- if tok!="HIERARCHY":
- raise SyntaxError, "Syntax error in line %d: 'HIERARCHY' expected, got '%s' instead"%(self.linenr, tok)
-
- tok = self.token()
- if tok!="ROOT":
- raise SyntaxError, "Syntax error in line %d: 'ROOT' expected, got '%s' instead"%(self.linenr, tok)
-
- self._root = Node(root=True)
- self._nodestack.append(self._root)
- self.readNode()
-
- # readNode
- def readNode(self):
- """Read the data for a node.
- """
-
- # Read the node name (or the word 'Site' if it was a 'End Site'
- # node)
- name = self.token()
- self._nodestack[-1].name = name
-
- tok = self.token()
- if tok!="{":
- raise SyntaxError, "Syntax error in line %d: '{' expected, got '%s' instead"%(self.linenr, tok)
-
- while 1:
- tok = self.token()
- if tok=="OFFSET":
- x = self.floatToken()
- y = self.floatToken()
- z = self.floatToken()
- self._nodestack[-1].offset = (x,y,z)
- elif tok=="CHANNELS":
- n = self.intToken()
- channels = []
- for i in range(n):
- tok = self.token()
- if tok not in ["Xposition", "Yposition", "Zposition",
- "Xrotation", "Yrotation", "Zrotation"]:
- raise SyntaxError, "Syntax error in line %d: Invalid channel name: '%s'"%(self.linenr, tok)
- channels.append(tok)
- self._numchannels += len(channels)
- self._nodestack[-1].channels = channels
- elif tok=="JOINT":
- node = Node()
- self._nodestack[-1].children.append(node)
- self._nodestack.append(node)
- self.readNode()
- elif tok=="End":
- node = Node()
- self._nodestack[-1].children.append(node)
- self._nodestack.append(node)
- self.readNode()
- elif tok=="}":
- if self._nodestack[-1].isEndSite():
- self._nodestack[-1].name = "End Site"
- self._nodestack.pop()
- break
- else:
- raise SyntaxError, "Syntax error in line %d: Unknown keyword '%s'"%(self.linenr, tok)
-
-
- # intToken
- def intToken(self):
- """Return the next token which must be an int.
- """
-
- tok = self.token()
- try:
- return int(tok)
- except ValueError:
- raise SyntaxError, "Syntax error in line %d: Integer expected, got '%s' instead"%(self.linenr, tok)
-
- # floatToken
- def floatToken(self):
- """Return the next token which must be a float.
- """
-
- tok = self.token()
- try:
- return float(tok)
- except ValueError:
- raise SyntaxError, "Syntax error in line %d: Float expected, got '%s' instead"%(self.linenr, tok)
-
- # token
- def token(self):
- """Return the next token."""
-
- # Are there still some tokens left? then just return the next one
- if self.tokenlist!=[]:
- tok = self.tokenlist[0]
- self.tokenlist = self.tokenlist[1:]
- return tok
-
- # Read a new line
- s = self.readLine()
- self.createTokens(s)
- return self.token()
-
- # readLine
- def readLine(self):
- """Return the next line.
-
- Empty lines are skipped. If the end of the file has been
- reached, a StopIteration exception is thrown. The return
- value is the next line containing data (this will never be an
- empty string).
- """
- # Discard any remaining tokens
- self.tokenlist = []
-
- # Read the next line
- while 1:
- s = self.fhandle.readline()
- self.linenr += 1
- if s=="":
- raise StopIteration
- return s
-
- # createTokens
- def createTokens(self, s):
- """Populate the token list from the content of s.
- """
- s = s.strip()
- a = s.split()
- self.tokenlist = a
-
-
-