home *** CD-ROM | disk | FTP | other *** search
/ Hackers Magazine 57 / CdHackersMagazineNr57.iso / Software / Multimedia / k3d-setup-0.7.11.0.exe / lib / site-packages / cgkit / bvh.py < prev    next >
Encoding:
Python Source  |  2007-01-11  |  8.5 KB  |  272 lines

  1. # ***** BEGIN LICENSE BLOCK *****
  2. # Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3. #
  4. # The contents of this file are subject to the Mozilla Public License Version
  5. # 1.1 (the "License"); you may not use this file except in compliance with
  6. # the License. You may obtain a copy of the License at
  7. # http://www.mozilla.org/MPL/
  8. #
  9. # Software distributed under the License is distributed on an "AS IS" basis,
  10. # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11. # for the specific language governing rights and limitations under the
  12. # License.
  13. #
  14. # The Original Code is the Python Computer Graphics Kit.
  15. #
  16. # The Initial Developer of the Original Code is Matthias Baas.
  17. # Portions created by the Initial Developer are Copyright (C) 2004
  18. # the Initial Developer. All Rights Reserved.
  19. #
  20. # Contributor(s):
  21. #
  22. # Alternatively, the contents of this file may be used under the terms of
  23. # either the GNU General Public License Version 2 or later (the "GPL"), or
  24. # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  25. # in which case the provisions of the GPL or the LGPL are applicable instead
  26. # of those above. If you wish to allow use of your version of this file only
  27. # under the terms of either the GPL or the LGPL, and not to allow others to
  28. # use your version of this file under the terms of the MPL, indicate your
  29. # decision by deleting the provisions above and replace them with the notice
  30. # and other provisions required by the GPL or the LGPL. If you do not delete
  31. # the provisions above, a recipient may use your version of this file under
  32. # the terms of any one of the MPL, the GPL or the LGPL.
  33. #
  34. # ***** END LICENSE BLOCK *****
  35. # $Id: bvh.py,v 1.1 2005/02/06 22:26:02 mbaas Exp $
  36.  
  37. ## \file bvh.py
  38. ## Contains the BVHReader class.
  39.  
  40. import string
  41.  
  42. # Node
  43. class Node:
  44.     def __init__(self, root=False):
  45.         self.name = None
  46.         self.channels = []
  47.         self.offset = (0,0,0)
  48.         self.children = []
  49.         self._is_root = root
  50.  
  51.     def isRoot(self):
  52.         return self._is_root
  53.  
  54.     def isEndSite(self):
  55.         return len(self.children)==0
  56.     
  57.  
  58. # BVHReader
  59. class BVHReader:
  60.     """Read BioVision Hierarchical (BVH) files.
  61.     """
  62.  
  63.     def __init__(self, filename):
  64.  
  65.         self.filename = filename
  66.         # A list of unprocessed tokens (strings)
  67.         self.tokenlist = []
  68.         # The current line number
  69.         self.linenr = 0
  70.  
  71.         # Root node
  72.         self._root = None
  73.         self._nodestack = []
  74.  
  75.         # Total number of channels
  76.         self._numchannels = 0
  77.  
  78.     def onHierarchy(self, root):
  79.         pass
  80.  
  81.     def onMotion(self, frames, dt):
  82.         pass
  83.  
  84.     def onFrame(self, values):
  85.         pass
  86.  
  87.     # read
  88.     def read(self):
  89.         """Read the entire file.
  90.         """
  91.         self.fhandle = file(self.filename)
  92.  
  93.         self.readHierarchy()
  94.         self.onHierarchy(self._root)
  95.         self.readMotion()
  96.  
  97.     # readMotion
  98.     def readMotion(self):
  99.         """Read the motion samples.
  100.         """
  101.         # No more tokens (i.e. end of file)? Then just return 
  102.         try:
  103.             tok = self.token()
  104.         except StopIteration:
  105.             return
  106.         
  107.         if tok!="MOTION":
  108.             raise SyntaxError, "Syntax error in line %d: 'MOTION' expected, got '%s' instead"%(self.linenr, tok)
  109.  
  110.         # Read the number of frames
  111.         tok = self.token()
  112.         if tok!="Frames:":
  113.             raise SyntaxError, "Syntax error in line %d: 'Frames:' expected, got '%s' instead"%(self.linenr, tok)
  114.  
  115.         frames = self.intToken()
  116.  
  117.         # Read the frame time
  118.         tok = self.token()
  119.         if tok!="Frame":
  120.             raise SyntaxError, "Syntax error in line %d: 'Frame Time:' expected, got '%s' instead"%(self.linenr, tok)
  121.         tok = self.token()
  122.         if tok!="Time:":
  123.             raise SyntaxError, "Syntax error in line %d: 'Frame Time:' expected, got 'Frame %s' instead"%(self.linenr, tok)
  124.  
  125.         dt = self.floatToken()
  126.  
  127.         self.onMotion(frames, dt)
  128.  
  129.         # Read the channel values
  130.         for i in range(frames):
  131.             s = self.readLine()
  132.             a = s.split()
  133.             if len(a)!=self._numchannels:
  134.                 raise SyntaxError, "Syntax error in line %d: %d float values expected, got %d instead"%(self.linenr, self._numchannels, len(a))
  135.             values = map(lambda x: float(x), a)
  136.             self.onFrame(values)
  137.  
  138.  
  139.     # readHierarchy
  140.     def readHierarchy(self):
  141.         """Read the skeleton hierarchy.
  142.         """
  143.         tok = self.token()
  144.         if tok!="HIERARCHY":
  145.             raise SyntaxError, "Syntax error in line %d: 'HIERARCHY' expected, got '%s' instead"%(self.linenr, tok)
  146.  
  147.         tok = self.token()
  148.         if tok!="ROOT":
  149.             raise SyntaxError, "Syntax error in line %d: 'ROOT' expected, got '%s' instead"%(self.linenr, tok)
  150.  
  151.         self._root = Node(root=True)
  152.         self._nodestack.append(self._root)
  153.         self.readNode()
  154.  
  155.     # readNode
  156.     def readNode(self):
  157.         """Read the data for a node.
  158.         """
  159.  
  160.         # Read the node name (or the word 'Site' if it was a 'End Site'
  161.         # node)
  162.         name = self.token()
  163.         self._nodestack[-1].name = name
  164.         
  165.         tok = self.token()
  166.         if tok!="{":
  167.             raise SyntaxError, "Syntax error in line %d: '{' expected, got '%s' instead"%(self.linenr, tok)
  168.  
  169.         while 1:
  170.             tok = self.token()
  171.             if tok=="OFFSET":
  172.                 x = self.floatToken()
  173.                 y = self.floatToken()
  174.                 z = self.floatToken()
  175.                 self._nodestack[-1].offset = (x,y,z)
  176.             elif tok=="CHANNELS":
  177.                 n = self.intToken()
  178.                 channels = []
  179.                 for i in range(n):
  180.                     tok = self.token()
  181.                     if tok not in ["Xposition", "Yposition", "Zposition",
  182.                                   "Xrotation", "Yrotation", "Zrotation"]:
  183.                         raise SyntaxError, "Syntax error in line %d: Invalid channel name: '%s'"%(self.linenr, tok)                        
  184.                     channels.append(tok)
  185.                 self._numchannels += len(channels)
  186.                 self._nodestack[-1].channels = channels
  187.             elif tok=="JOINT":
  188.                 node = Node()
  189.                 self._nodestack[-1].children.append(node)
  190.                 self._nodestack.append(node)
  191.                 self.readNode()
  192.             elif tok=="End":
  193.                 node = Node()
  194.                 self._nodestack[-1].children.append(node)
  195.                 self._nodestack.append(node)
  196.                 self.readNode()
  197.             elif tok=="}":
  198.                 if self._nodestack[-1].isEndSite():
  199.                     self._nodestack[-1].name = "End Site"
  200.                 self._nodestack.pop()
  201.                 break
  202.             else:
  203.                 raise SyntaxError, "Syntax error in line %d: Unknown keyword '%s'"%(self.linenr, tok)
  204.         
  205.  
  206.     # intToken
  207.     def intToken(self):
  208.         """Return the next token which must be an int.
  209.         """
  210.  
  211.         tok = self.token()
  212.         try:
  213.             return int(tok)
  214.         except ValueError:
  215.             raise SyntaxError, "Syntax error in line %d: Integer expected, got '%s' instead"%(self.linenr, tok)
  216.  
  217.     # floatToken
  218.     def floatToken(self):
  219.         """Return the next token which must be a float.
  220.         """
  221.  
  222.         tok = self.token()
  223.         try:
  224.             return float(tok)
  225.         except ValueError:
  226.             raise SyntaxError, "Syntax error in line %d: Float expected, got '%s' instead"%(self.linenr, tok)
  227.  
  228.     # token
  229.     def token(self):
  230.         """Return the next token."""
  231.  
  232.         # Are there still some tokens left? then just return the next one
  233.         if self.tokenlist!=[]:
  234.             tok = self.tokenlist[0]
  235.             self.tokenlist = self.tokenlist[1:]
  236.             return tok
  237.  
  238.         # Read a new line
  239.         s = self.readLine()
  240.         self.createTokens(s)
  241.         return self.token()
  242.  
  243.     # readLine
  244.     def readLine(self):
  245.         """Return the next line.
  246.  
  247.         Empty lines are skipped. If the end of the file has been
  248.         reached, a StopIteration exception is thrown.  The return
  249.         value is the next line containing data (this will never be an
  250.         empty string).
  251.         """
  252.         # Discard any remaining tokens
  253.         self.tokenlist = []
  254.       
  255.         # Read the next line
  256.         while 1:
  257.             s = self.fhandle.readline()
  258.             self.linenr += 1
  259.             if s=="":
  260.                 raise StopIteration
  261.             return s
  262.  
  263.     # createTokens
  264.     def createTokens(self, s):
  265.         """Populate the token list from the content of s.
  266.         """
  267.         s = s.strip()
  268.         a = s.split()
  269.         self.tokenlist = a
  270.  
  271.     
  272.