This is only beginning of the bindings here. It's starting to get more complicated due to the use of callbacks. To be able to define a callback function in Python which is then called by a C++ algorithm requires quite a bit of wrapping boilerplate. The class PyCallback here will wrap a Python callable and call it with the density value of the voxel. It's not very generic and at present it can't pass the sampler itself since it's not available in the Python bindings. Regardless, the new test added here (TestRaycast.py) works as expected and hopefully we will be able to build up from here.
55 lines
1.8 KiB
OpenEdge ABL
55 lines
1.8 KiB
OpenEdge ABL
%module Raycast
|
|
%{
|
|
#include "Raycast.h"
|
|
|
|
template<typename VolumeType>
|
|
class PyCallback
|
|
{
|
|
private:
|
|
PyObject *func;
|
|
PyCallback& operator=(const PyCallback&); // Not allowed
|
|
public:
|
|
PyCallback(const PyCallback& o) : func(o.func)
|
|
{
|
|
Py_XINCREF(func);
|
|
}
|
|
PyCallback(PyObject *func) : func(func)
|
|
{
|
|
Py_XINCREF(this->func);
|
|
assert(PyCallable_Check(this->func));
|
|
}
|
|
~PyCallback()
|
|
{
|
|
Py_XDECREF(func);
|
|
}
|
|
bool operator()(const typename VolumeType::Sampler& sampler)
|
|
{
|
|
if (!func || Py_None == func || !PyCallable_Check(func))
|
|
{
|
|
return false; //Make this raise a Python exception
|
|
}
|
|
PyObject *args = Py_BuildValue("(l)", sampler.getVoxel().getDensity()); //TODO pass the sampler object itself in
|
|
PyObject *result = PyObject_Call(func,args,0);
|
|
Py_DECREF(args);
|
|
Py_XDECREF(result);
|
|
return (PyInt_AsLong(result) == 0) ? false : true;
|
|
}
|
|
};
|
|
|
|
template<typename VolumeType, typename Callback>
|
|
PolyVox::RaycastResult raycastWithEndpointsPython(VolumeType* volData, const PolyVox::Vector3DFloat& v3dStart, const PolyVox::Vector3DFloat& v3dEnd, PyObject *callback)
|
|
{
|
|
PyCallback<VolumeType> newCallback(callback);
|
|
return PolyVox::raycastWithEndpoints(volData, v3dStart, v3dEnd, newCallback);
|
|
}
|
|
|
|
%}
|
|
|
|
%include "Raycast.h"
|
|
|
|
template<typename VolumeType, typename Callback>
|
|
PolyVox::RaycastResult raycastWithEndpointsPython(VolumeType* volData, const PolyVox::Vector3DFloat& v3dStart, const PolyVox::Vector3DFloat& v3dEnd, PyObject *callback);
|
|
|
|
%template(raycastWithEndpointsSimpleVolumeDensity8) raycastWithEndpointsPython<PolyVox::SimpleVolume<PolyVox::Density8>, PyCallback<PolyVox::SimpleVolume<PolyVox::Density8> > >;
|
|
//%template(raycastWithEndpointsSimpleVolumeMaterial8) raycastWithEndpointsPython<PolyVox::SimpleVolume<PolyVox::Material8>, PyCallback<PolyVox::SimpleVolume<PolyVox::Material8> > >;
|