如何在Blender Python API中直接获取顶点C指针以避免数据复制?
如何在Python中直接获取Blender网格顶点的C指针以避免数据复制?
我正在为Blender开发一款C/C++渲染引擎,目标是通过C指针直接访问网格顶点,减少Python层耗时并避免不必要的数据复制。
尝试过的方法及问题
- 我了解到继承自ID类的对象拥有
as_pointer()方法,但尝试对网格的vertices集合调用该方法时:
出现错误,提示mesh = bpy.context.object.data pointer = mesh.vertices.as_pointer()bpy_prop_collection对象无as_pointer属性——这符合预期,因为bpy_prop_collection并非ID类的子类。 - 文档显示
vertices的类型为“MeshVertices bpy_prop_collection of MeshVertex, (readonly)”,且MeshVertices应该可以返回指针,但实际使用中,vertices及其元素都不属于该类型,无法通过这种方式获取指针。
当前的替代方案(存在数据复制开销)
目前我采用的方式是将顶点数据读取到numpy数组后再传递给C库,示例代码如下:
import bpy import numpy as np import ctypes obj = bpy.context.object # 假设'obj'是网格对象 mesh = obj.data # 分配数组并复制数据,然后将结构体指针指向该数组 vert_array = np.zeros((len(mesh.vertices) * 3), dtype=np.float32) mesh.vertices.foreach_get("co", vert_array) vert_ptr = vert_array.ctypes.data_as(ctypes.POINTER(ctypes.c_float)) # 传递指针 lib = ctypes.CDLL("bin/libengine.so") lib.load_vert.argtypes = [ctypes.POINTER(ctypes.float)] lib.load_vert(vert_ptr)
但这种方式会在内存中复制顶点数据(一份在Blender内部结构,一份在numpy数组),存在可避免的处理开销。
底层C API的直接访问可能性
查看Blender源码后发现,底层C/C++ API支持直接内存访问:顶点数据存储在连续的内存块中,可通过BKE_mesh_vert_positions和CustomData_get_layer_named函数直接获取指针:
BLI_INLINE const float (*BKE_mesh_vert_positions(const Mesh *mesh))[3] { return (const float(*)[3])CustomData_get_layer_named(&mesh->vdata, CD_PROP_FLOAT3, "position"); }
const void *CustomData_get_layer_named(const CustomData *data, const eCustomDataType type, const char *name) { int layer_index = CustomData_get_named_layer_index(data, type, name); if (layer_index == -1) { return nullptr; } return data->layers[layer_index].data; }
理论上可以直接获取该数据指针。
核心问题
是否有方法通过Python API暴露这些指针,或者无需编译自定义Blender版本,从Python调用C/C++ API直接获取该内存?任何关于直接获取指针或避免数据复制的替代方案指导都将非常感谢。
内容的提问来源于stack exchange,提问作者Elzaidir
相关产品推荐
相关产品推荐

