I've been looking for another solution that doesn't swap out code in
pyglet.graphics, and doesn't break the vertex list interface for
existing layers, like pyglet.sprite.
Here's another version that uses a subclassed Batch to return custom
VertexList and IndexedVertexList objects that support numpy arrays for
vertex attributes. The numpy arrays are made available though an
attribute 'n' of the vertex list (i.e vlist.n.vertices instead of
vlist.vertices) so it doesn't change the existing interface.
>>> b = nverts2.Batch()
>>> v = b.add(4, 0, None, 'v3f')
# normal c_array access
>>> v.vertices[:]
# numpy ndarray access
>>> v.n.vertices
Any one have thoughts on designing an interface to Numpy ndarray views
with pyglet.graphics?
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"pyglet-users" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/pyglet-users?hl=en
-~----------~----~----~----~------~----~------~--~---
"""
Numpy array integration with pyglet.graphics.
"""
import numpy
import ctypes
import pyglet
from pyglet.graphics import vertexdomain
ctypes.pythonapi.PyBuffer_FromReadWriteMemory.restype = ctypes.py_object
def as_numpy_array(c_array):
"""
Return a view of the c array as a numpy array, with the
underlying memory shared.
"""
return numpy.frombuffer(
ctypes.pythonapi.PyBuffer_FromReadWriteMemory(
c_array, ctypes.sizeof(c_array._type_) * len(c_array)),
dtype=c_array._type_)
class Batch(pyglet.graphics.Batch):
__doc__ = pyglet.graphics.Batch.__doc__
def add(self, count, mode, group, *data):
formats, initial_arrays = pyglet.graphics._parse_data(data)
domain = self._get_domain(False, mode, group, formats)
domain.__formats = formats
# Create vertex list and initialize
start = domain._safe_alloc(count)
vlist = VertexList(domain, start, count)
for i, array in initial_arrays:
vlist._set_attribute_data(i, array)
return vlist
add.__doc__ = pyglet.graphics.Batch.add.__doc__
def add_indexed(self, count, mode, group, indices, *data):
formats, initial_arrays = pyglet.graphics._parse_data(data)
domain = self._get_domain(True, mode, group, formats)
# Create vertex list and initialize
start = domain._safe_alloc(count)
index_start = domain._safe_index_alloc(len(indices))
vlist = IndexedVertexList(
domain, start, count, index_start, len(indices))
vlist._set_index_data(map(lambda i: i + start, indices))
for i, array in initial_arrays:
vlist._set_attribute_data(i, array)
return vlist
add_indexed.__doc__ = pyglet.graphics.Batch.add_indexed.__doc__
class Nviews(object):
"""
Container for accessing vertex attributes as Numpy ndarrays.
"""
def __init__(self, vertexlist):
self._vlist = vertexlist
def _get_shaped_array(self, attribute_name):
"""
Shapes and transposes the arrays retrieved by the
vertexattribute property descriptors to reflect the
vertex/attribute counts.
"""
array = getattr(self._vlist, '_get_%s' % attribute_name)()
region = getattr(self._vlist, '_%s_cache' % attribute_name)
if not hasattr(region, 'ndarray'):
count = self._vlist.domain.attribute_names[attribute_name].count
ndarray = as_numpy_array(array)
ndarray.shape = (len(array) / count, count)
ndarray = ndarray.transpose()
region = getattr(self._vlist, '_%s_cache' % attribute_name)
region.ndarray = ndarray
return region.ndarray
def _get_colors(self):
return self._get_shaped_array('colors')
def _get_fog_coords(self):
return self._get_shaped_array('fog_coords')
def _get_edge_flags(self):
return self._get_shaped_array('edge_flags')
def _get_normals(self):
return self._get_shaped_array('normals')
def _get_secondary_colors(self):
return self._get_shaped_array('secondary_colors')
def _get_tex_coords(self):
return self._get_shaped_array('tex_coords')
def _get_vertices(self):
return self._get_shaped_array('vertices')
colors = property(
_get_colors, vertexdomain.VertexList._set_colors,
doc=vertexdomain.VertexList.colors.__doc__)
fog_coords = property(
_get_fog_coords, vertexdomain.VertexList._set_fog_coords,
doc=vertexdomain.VertexList.fog_coords.__doc__)
edge_flags = property(
_get_edge_flags, vertexdomain.VertexList._set_edge_flags,
doc=vertexdomain.VertexList.edge_flags.__doc__)
normals = property(
_get_normals, vertexdomain.VertexList._set_normals,
doc=vertexdomain.VertexList.normals.__doc__)
tex_coords = property(
_get_tex_coords, vertexdomain.VertexList._set_tex_coords,
doc=vertexdomain.VertexList.tex_coords.__doc__)
vertices = property(
_get_vertices, vertexdomain.VertexList._set_vertices,
doc=vertexdomain.VertexList.vertices.__doc__)
class VertexList(vertexdomain.VertexList):
__doc__ = vertexdomain.VertexList.__doc__
def __init__(self, domain, start, count):
super(VertexList, self).__init__(domain, start, count)
self._n = Nviews(self)
n = property(lambda self: self._n)
class IndexedVertexList(VertexList, vertexdomain.IndexedVertexList):
__doc__ = vertexdomain.IndexedVertexList.__doc__
def __init__(self, domain, start, count, index_start, index_count):
vertexdomain.IndexedVertexList.__init__(
self, domain, start, count, index_start, index_count)
self._n = Nviews(self)