home *** CD-ROM | disk | FTP | other *** search
/ Hackers Magazine 57 / CdHackersMagazineNr57.iso / Software / Multimedia / k3d-setup-0.7.11.0.exe / lib / site-packages / OpenGL / arrays / lists.py < prev    next >
Encoding:
Python Source  |  2009-01-03  |  5.5 KB  |  170 lines

  1. """Lists/tuples as data-format for storage
  2.  
  3. Note:
  4.     This implementation is *far* less efficient than using Numpy
  5.     to support lists/tuples, as the code here is all available in
  6.     C-level code there.  This implementation is required to allow
  7.     for usage without numpy installed.
  8. """
  9. REGISTRY_NAME = 'ctypesarrays'
  10. import ctypes, _ctypes
  11.  
  12. from OpenGL import constants, constant
  13. from OpenGL.arrays import formathandler
  14. #try:
  15. #    from OpenGL.arrays import numpymodule
  16. #except ImportError, err:
  17. #    # we are required...
  18. HANDLED_TYPES = (list,tuple)
  19. #else:
  20. #    HANDLED_TYPES = ()
  21. import operator
  22.  
  23. class ListHandler( formathandler.FormatHandler ):
  24.     """Storage of array data in Python lists/arrays
  25.  
  26.     This mechanism, unlike multi-dimensional arrays, is not necessarily
  27.     uniform in type or dimension, so we have to do a lot of extra checks
  28.     to make sure that we get a correctly-structured array.  That, as
  29.     well as the need to copy the arrays in Python code, makes this a far
  30.     less efficient implementation than the numpy implementation, which
  31.     does all the same things, but does them all in C code.
  32.  
  33.     Note: as an *output* format, this format handler produces ctypes
  34.         arrays, not Python lists, this is done for convenience in coding
  35.         the implementation, mostly.
  36.     """
  37.     def from_param( self, instance, typeCode=None ):
  38.         try:
  39.             return ctypes.byref( instance )
  40.         except TypeError, err:
  41.             array = self.asArray( instance, typeCode )
  42.             pp = ctypes.c_void_p( ctypes.addressof( array ) )
  43.             pp._temporary_array_ = (array,)
  44.             return pp
  45.     dataPointer = staticmethod( ctypes.addressof )
  46.     HANDLED_TYPES = HANDLED_TYPES 
  47.     isOutput = True
  48.     def voidDataPointer( cls, value ):
  49.         """Given value in a known data-pointer type, return void_p for pointer"""
  50.         return ctypes.byref( value )
  51.     def zeros( self, dims, typeCode ):
  52.         """Return array of zeros in given size"""
  53.         type = GL_TYPE_TO_ARRAY_MAPPING[ typeCode ]
  54.         for dim in dims:
  55.             type *= dim 
  56.         return type() # should expicitly set to 0s
  57.     def dimsOf( cls, x ):
  58.         """Calculate total dimension-set of the elements in x
  59.         
  60.         This is *extremely* messy, as it has to track nested arrays
  61.         where the arrays could be different sizes on all sorts of 
  62.         levels...
  63.         """
  64.         try:
  65.             dimensions = [ len(x) ]
  66.         except (TypeError,AttributeError,ValueError), err:
  67.             return []
  68.         else:
  69.             childDimension = None
  70.             for child in x:
  71.                 newDimension = cls.dimsOf( child )
  72.                 if childDimension is not None:
  73.                     if newDimension != childDimension:
  74.                         raise ValueError( 
  75.                             """Non-uniform array encountered: %s versus %s"""%(
  76.                                 newDimension, childDimension,
  77.                             ), x
  78.                         )
  79.     dimsOf = classmethod( dimsOf )
  80.  
  81.     def arrayToGLType( self, value ):
  82.         """Given a value, guess OpenGL type of the corresponding pointer"""
  83.  
  84.         result = ARRAY_TO_GL_TYPE_MAPPING.get( value._type_ )
  85.         if result is not None:
  86.             return result
  87.         raise TypeError(
  88.             """Don't know GL type for array of type %r, known types: %s\nvalue:%s"""%(
  89.                 value._type_, ARRAY_TO_GL_TYPE_MAPPING.keys(), value,
  90.             )
  91.         )
  92.     def arraySize( self, value, typeCode = None ):
  93.         """Given a data-value, calculate dimensions for the array"""
  94.         dims = 1
  95.         for base in self.types( value ):
  96.             length = getattr( base, '_length_', None)
  97.             if length is not None:
  98.                 dims *= length
  99.         return dims 
  100.     def types( self, value ):
  101.         """Produce iterable producing all composite types"""
  102.         dimObject = value
  103.         while dimObject is not None:
  104.             yield dimObject
  105.             dimObject = getattr( dimObject, '_type_', None )
  106.             if isinstance( dimObject, (str,unicode)):
  107.                 dimObject = None 
  108.     def dims( self, value ):
  109.         """Produce iterable of all dimensions"""
  110.         for base in self.types( value ):
  111.             length = getattr( base, '_length_', None)
  112.             if length is not None:
  113.                 yield length
  114.     def asArray( self, value, typeCode=None ):
  115.         """Convert given value to a ctypes array value of given typeCode
  116.         
  117.         This does a *lot* of work just to get the data into the correct
  118.         format.  It's not going to be anywhere near as fast as a numpy
  119.         or similar approach!
  120.         """
  121.         if typeCode is None:
  122.             raise NotImplementedError( """Haven't implemented type-inference for lists yet""" )
  123.         arrayType = GL_TYPE_TO_ARRAY_MAPPING[ typeCode ]
  124.         if isinstance( value, (list,tuple)):
  125.             subItems = [
  126.                 self.asArray( item, typeCode )
  127.                 for item in value
  128.             ]
  129.             if subItems:
  130.                 for dim in self.dimensions( subItems[0] )[::-1]:
  131.                     arrayType *= dim
  132.                 arrayType *= len( subItems )
  133.                 result = arrayType()
  134.                 result[:] = subItems
  135.                 return result
  136.         else:
  137.             return arrayType( value )
  138.     def unitSize( self, value, typeCode=None ):
  139.         """Determine unit size of an array (if possible)"""
  140.         return tuple(self.dims(value))[-1]
  141.     def dimensions( self, value, typeCode=None ):
  142.         """Determine dimensions of the passed array value (if possible)"""
  143.         return tuple( self.dims(value) )
  144.  
  145.  
  146. ARRAY_TO_GL_TYPE_MAPPING = {
  147.     constants.GLdouble: constants.GL_DOUBLE,
  148.     constants.GLfloat: constants.GL_FLOAT,
  149.     constants.GLint: constants.GL_INT,
  150.     constants.GLuint: constants.GL_UNSIGNED_INT,
  151.     constants.GLshort: constants.GL_SHORT,
  152.     constants.GLushort: constants.GL_UNSIGNED_SHORT,
  153.         
  154.     constants.GLchar: constants.GL_CHAR,
  155.     constants.GLbyte: constants.GL_BYTE,
  156.     constants.GLubyte: constants.GL_UNSIGNED_BYTE,
  157. }
  158. GL_TYPE_TO_ARRAY_MAPPING = {
  159.     constants.GL_DOUBLE: constants.GLdouble,
  160.     constants.GL_FLOAT: constants.GLfloat,
  161.     constants.GL_INT: constants.GLint,
  162.     constants.GL_UNSIGNED_INT: constants.GLuint,
  163.     constants.GL_SHORT: constants.GLshort,
  164.     constants.GL_UNSIGNED_SHORT: constants.GLushort,
  165.         
  166.     constants.GL_CHAR: constants.GLchar,
  167.     constants.GL_BYTE: constants.GLbyte,
  168.     constants.GL_UNSIGNED_BYTE: constants.GLubyte,
  169. }
  170.