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



_______________________________________________
Bf-committers mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-committers

Reply via email to