Skip to content

API Additions for Object Oriented Language Bindings #522

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
dbs4261 opened this issue Mar 13, 2025 · 0 comments
Open

API Additions for Object Oriented Language Bindings #522

dbs4261 opened this issue Mar 13, 2025 · 0 comments

Comments

@dbs4261
Copy link
Contributor

dbs4261 commented Mar 13, 2025

I've been working on writing some python binding code for an algorithm that relies on Embree. I ran into an issue when I found I needed to be able to efficiently add geometries to the Embree scene that the algorithm processes. When wrapping the Embree objects for Python, I found that many attributes are settable but not gettable through the API. This gets in the way of providing an object oriented binding for object oriented languages. The frustrating part is that I can see that most of these missing functions are exposed methods on the internal Embree objects that the C API wraps.

While making this I noticed the pyembree branch that @dopitz has been working on. Personally, I'm disappointed that it is a transliteration rather than a Pythonic API. But I suspect he has run into the issues I've had with getting data back out of Embree, and doing something more user friendly is difficult.

I went through the v4.3 C API and made a list of functions that, in my opinion, should be added to the API:

/**
* Buffer
*/

bool rtcIsBufferShared(RTCBuffer buffer);

size_t rtcGetBufferSize(RTCBuffer buffer);


/**
* Device
* (These seem less necessary)
*/

RTCErrorFunction rtcGetDeviceErrorFunction(RTCDevice device);
void* rtcGetDeviceErrorFunctionUserPtr(RTCDevice device);

RTCMemoryMonitorFunction rtcSetDeviceMemoryMonitorFunction(RTCDevice device);
void* rtcSetDeviceMemoryMonitorFunctionUserPtr(RTCDevice device);


/**
* Geometry
*/

enum RTCGeometryType rtcGetGeometryType(RTCGeometry geometry);

bool rtcIsGeometryCommitted(RTCGeometry geometry);

void rtcEnableGeometry(RTCGeometry geometry, bool enable); // Overload
bool rtcIsGeometryEnabled(RTCGeometry geometry);

struct RTCAccessor {
    RTCFormat format;
    RTCBuffer buffer;
    size_t byteOffset;
    size_t byteStride;
    size_t itemCount;
};

void rtcSetGeometryBuffer(RTCGeometry geometry, RTCBufferType type, unsigned int slot, RTCAccessor accessor);

RTCAccessor rtcGetGeometryBufferAccessor(RTCGeometry geometry, RTCBufferType type, unsigned int slot);

void rtcGetGeometryBufferAccessors(RTCGeometry geometry, RTCBufferType type, unsigned int* numSlots, RTCAccessor* accessors = nullptr); // like vulkan

void rtcGetGeometryInstancedScenes(RTCGeometry geometry, size_t* numScenes, RTCScene* scenes = nullptr); // like vulkan

bool rtcGetGeometryTransform(RTCGeometry geometry, unsigned int timestep, enum RTCFormat format, void* xfm); // overload

unsigned int rtcGetGeometryTimeStepCount(RTCGeometry geometry);
void rtcGetGeometryTimeRange(RTCGeometry geometry, float* startTime, float* endTime);

unsigned int rtcGetGeometryVertexAttributeCount(RTCGeometry geometry);

unsigned int rtcGetGeometryMask(RTCGeometry geometry);

unsigned int rtcGetGeometryUserPrimitiveCount(RTCGeometry geometry);

float rtcGetGeometryTessellationRate(RTCGeometry geometry);

unsigned int rtcGetGeometryTopologyCount(RTCGeometry geometry);

enum RTCSubdivisionMode rtcGetGeometrySubdivisionMode(RTCGeometry geometry, unsigned int topologyID);

unsigned int rtcGetGeometryVertexAttributeTopology(RTCGeometry geometry, unsigned int vertexAttributeID);

bool rtcIsGeometryFilterFunctionFromArguments(RTCGeometry geometry);
RTCFilterFunctionN rtcGetGeometryIntersectFilterFunction(RTCGeometry geometry);
RTCFilterFunctionN rtcGetGeometryOccludedFilterFunction(RTCGeometry geometry);

RTCPointQueryFunction rtcGetGeometryPointQueryFunction(RTCGeometry geometry);
RTCBoundsFunction rtcGetGeometryBoundsFunction(RTCGeometry geometry);
RTCIntersectFunctionN rtcGetGeometryIntersectFunction(RTCGeometry geometry);
RTCOccludedFunctionN rtcGetGeometryOccludedFunction(RTCGeometry geometry);
RTCDisplacementFunctionN rtcGetGeometryDisplacementFunction(RTCGeometry geometry);


/**
* Scene
*/

void rtcGetGeometryIDs(RTCScene scene, size_t* numGeomIDs, unsigned int* geomIDs = nullptr); // like vulkan

bool rtcIsSceneCommitted(RTCScene scene);

RTCProgressMonitorFunction rtcGetSceneProgressMonitorFunction(RTCScene scene);
void* rtcGetSceneProgressMonitorFunctionUserPtr(RTCScene scene);

enum RTCBuildQuality rtcGetSceneBuildQuality(RTCScene scene);

One larger change that I listed was adding an RTCAccessor struct based on the glTF Accessor so that the buffer binding parameters could be returned as a single structure. I would suggest returning a zero initialized structure for unpopulated but assignable slots on a geometry.

As a side note, what I mean by // like vulkan is that it returns a vector by two successive calls. The first call with the output pointer set to nullptr just gets the size of the resulting array. The user then allocates that memory, and calls the function again with the allocated pointer to get the array values. The default value would need to be wrapped in a macro controlled by EMBREE_API_NAMESPACE.

I'd also like to see a C++ header with compile time information. Some good information would be the buffer types attached to each geometry type, the number of slots for each buffer type, and the buffer formats allowed for each buffer type. But this is not necessary.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant