RenderKit / embree

Embree ray tracing kernels repository.
Apache License 2.0
2.32k stars 383 forks source link

Using buffers with user geometry #479

Open dmitrishastin opened 3 months ago

dmitrishastin commented 3 months ago

I've come across an issue where using vertex / index buffers with user geometry fails.

I don't know if I've missed it, but this does not appear to be mentioned in the documentation - so wanted to check if this is expected behaviour?

#define __SSE4_2__
#define TASKING_INTERNAL

#include <embree4/rtcore.h>
#include "../../common/default.h"

namespace embree {

    std::vector<std::tuple<RTCGeometryType, const void*, const void*>> geometry_ptrs_;

    void mesh_bounds_func(const struct RTCBoundsFunctionArguments* args)
    {
        BBox3fa bounds = empty;
        Vec3fa v0 = { -1.f, -1.f, -1.f };
        Vec3fa v1 = { 1.f,  1.f,  1.f };
        bounds.extend(v0);
        bounds.extend(v1);
        *(BBox3fa*)args->bounds_o = bounds;
    }

    unsigned int add_triangle(RTCScene scene, RTCDevice device) {

        RTCGeometryType geom_type = RTC_GEOMETRY_TYPE_TRIANGLE;
        RTCGeometry geom = rtcNewGeometry(device, geom_type);

        float* vertices = (float*)rtcSetNewGeometryBuffer(geom,
            RTC_BUFFER_TYPE_VERTEX,
            0,
            RTC_FORMAT_FLOAT3,
            3 * sizeof(float),
            3);

        unsigned* indices = (unsigned*)rtcSetNewGeometryBuffer(geom,
            RTC_BUFFER_TYPE_INDEX,
            0,
            RTC_FORMAT_UINT3,
            3 * sizeof(unsigned),
            1);

        if (vertices && indices)
        {
            vertices[0] = 2.5f; vertices[1] = 0.f; vertices[2] = 0.f;
            vertices[3] = 1.f; vertices[4] = 0.f; vertices[5] = 0.f;
            vertices[6] = 0.f; vertices[7] = 1.3f; vertices[8] = 0.f;
            indices[0] = 0; indices[1] = 1; indices[2] = 2;
        }

        unsigned int geomID = rtcAttachGeometry(scene, geom);

        if (geom_type == RTC_GEOMETRY_TYPE_USER) {
            rtcSetGeometryUserPrimitiveCount(geom, 1);
            rtcSetGeometryUserData(geom, (void*)(size_t)geomID);
            rtcSetGeometryBoundsFunction(geom, mesh_bounds_func, nullptr);
        }

        rtcCommitGeometry(geom);

        geometry_ptrs_.push_back(std::make_tuple(geom_type, (void*)vertices, (void*)indices));

        rtcReleaseGeometry(geom);

        return geomID;

    }

}

int main()
{

    RTCDevice device = rtcNewDevice(NULL);
    RTCScene sceneT = rtcNewScene(device);
    embree::add_triangle(sceneT, device);
    rtcCommitScene(sceneT);

    float* vertex_positions = (float*) std::get<1>(embree::geometry_ptrs_[0]);
    for (size_t i = 0; i < 9; ++i) {
        std::cout << "v" << i << " = " << vertex_positions[i] << std::endl;
    }

    rtcReleaseScene(sceneT);
    rtcReleaseDevice(device);

    return 0;
}

Output:

v0 = 2.5 v1 = 0 v2 = 0 v3 = 1 v4 = 0 v5 = 0 v6 = 0 v7 = 1.3 v8 = 0

Changing geom_type to RTC_GEOMETRY_TYPE_USER throws a read access violation.

Will be grateful for comments - thanks!