[Bf-committers] generic memoryviews
Theo de Ridder
theo.de.ridder at planet.nl
Sat Jun 12 19:24:07 CEST 2010
For those appreciating 'Pythonic' solutions
here is a design for generating memoryviews
for any bpy collection object.
My intentions:
a) memoryviews that enable high performance in pure Python
for handling individual elements of huge (multidimensional)
collections of Blender data by delegating low level (vertices, pixels, ...)
getter/setter loops to the C-level;
b) a generic composition that is small, robust, and a natural fit
with modern concepts in Blender and Python.
My solution is represented by the following types and attributes
(to be builtins in C):
1. class Slicer:
__getitem__(...): generates a ViewWrapper context manager from standard slice notation;
2. class ViewWrapper:
__enter__(...): creates a tempory MemCache, and subscribes to supplier;
__exit__(...): disables the tempory MemCache, and unsubscribes from supplier;
supplier: ref to original collection object
memcache: generated MemCache
refresh(...): refresh memcache from original
update(...): update original from memcache
3: class MemCache (memoryview):
wrapper: ref to original ViewWrapper
- Any MemCache can be subsliced as a normal memoryview,
and the refresh/update methods can have such a subview as
an optional argument to restrict datatransfer to a limited area.
- Any Memcache is robust against lost pointers and changing collections when:
- the deletion of a collection is notifying its subscribing ViewWrappers;
- a MemCache as argument of a refresh or update is checked for:
- its supplier is still living;
- its axes and sizes are stiil compliant with those of the supplier;
examples of slicing:
mesh = bpy.data.meshes['Cube']
wrapnormals = Slicer(mesh.faces)[:, 'normal', :]
wrapverts = Slicer(mesh.verts)[:, 'co', :]
wrap3xyz = Slicer(mesh.verts)[:, co', ('xxx', 'yyy', 'zzz'), :]
wrapvertcolors = Slicer(mesh.vertex_colors)[['Col'], 'data', :, ('color1', 'color2'), :]
example of usage:
- def updater (name):
# yielding enables reentering context without overhead of __enter__
slicer = Slicer(bpy.data.meshes[name].faces)
with slicer['normals', :] as vw:
subcache = yield vw.memcache
while True:
info = ...
subcache = yield info
i if subcache == None:
break
vw.update(subcache)
generator = updater('Monkey')
memcache = gen.next()
while not stop_condition():
i,j = ...
subcache = memcache[i:j, :]
modify(subcache)
info = gen.send(subcache)
so far, so good;
if there is interest I am willing to work out this idea into a full Python
executable specification (including performance analysis with numpy in Blender 2.49),
however, I am feeling sorry being too old now for
hacking again in C after more than 20 years,
~Theo
More information about the Bf-committers
mailing list