Intel® Embree Ray Tracing Kernels
Discussion forum on the open source ray tracing kernels for fast photo-realistic rendering on Intel® CPU(s)
288 Discussions

Is it possible to use Embree for intersection computation in 2D ?

ImperatorS79
New User
187 Views

I see there is RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE, but despite all my attemps, I do not maange to make it work.  Here is my last attempt:

 

#include <array>
#include <vector>
#include <string>
#include <stdexcept>
#include <iostream>
#include <limits>
#include <embree4/rtcore.h>

std::string translateEmbreeError(RTCError error)
{
switch(error)
{
case RTC_ERROR_NONE:
return "no error occured";
case RTC_ERROR_INVALID_ARGUMENT:
return "an unknown error has occured";
case RTC_ERROR_INVALID_OPERATION:
return "the operation is not allowed for the specified object";
case RTC_ERROR_OUT_OF_MEMORY:
return "there is not enough memory left to complete the operation";
case RTC_ERROR_UNSUPPORTED_CPU:
return "the CPU is not supported as it does not support the lowest ISA Embree is compiled for";
case RTC_ERROR_CANCELLED:
return "the operation got canceled by a memory monitor callback or progress monitor callback function";
default:
return "unknown error";
}
}

struct RayQueryContext
{
RTCRayQueryContext context;
unsigned int skipFacet;
};

void intersectionFilter(const RTCFilterFunctionNArguments* args);

int main()
{
RTCDevice device = rtcNewDevice("set_affinity=1");
if(device == NULL)
throw std::runtime_error("failed to create embree device: " + translateEmbreeError(rtcGetDeviceError(NULL)));

RTCScene scene = rtcNewScene(device);
RTCError error = rtcGetDeviceError(device);
if(scene == NULL)
throw std::runtime_error("failed to create embree scene: " + translateEmbreeError(error));

rtcSetSceneFlags(scene, RTC_SCENE_FLAG_FILTER_FUNCTION_IN_ARGUMENTS | RTC_SCENE_FLAG_ROBUST);
error = rtcGetDeviceError(device);
if(error != RTC_ERROR_NONE)
throw std::runtime_error("failed to set embree scene flags: " + translateEmbreeError(error));

RTCGeometry geom = rtcNewGeometry(device, RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE);
error = rtcGetDeviceError(device);
if(geom == NULL)
throw std::runtime_error("failed to create embree geometry: " + translateEmbreeError(error));

rtcSetGeometryEnableFilterFunctionFromArguments(geom, true);
error = rtcGetDeviceError(device);
if(error != RTC_ERROR_NONE)
throw std::runtime_error("failed to set embree geometry flags: " + translateEmbreeError(error));

std::vector<std::array<double, 3>> points = {
{0.0f, 0.0f, 0.0f}, {1.0f, 0.0f, 0.0f},
{1.0f, 0.0f, 0.0f}, {1.0f, -1.0f, 0.0f},
{1.0f, -1.0f, 0.0f}, {0.0f, -1.0f, 0.0f},
{0.0f, -1.0f, 0.0f}, {0.0f, 0.0f, 0.0f}
};

float* vb = static_cast<float*>(rtcSetNewGeometryBuffer(geom,
RTC_BUFFER_TYPE_VERTEX, 0, RTC_FORMAT_FLOAT4, 4*sizeof(float), points.size()));

const size_t segmentsCount = points.size()/2;

for(std::size_t s = 0 ; s < segmentsCount ; ++s)
{
//First point of segment
vb[8*s + 0] = points[2*s + 0][0];
vb[8*s + 1] = points[2*s + 0][1];
vb[8*s + 2] = 0.0f;
vb[8*s + 3] = 0.1f;
//Second point of segment
vb[8*s + 4] = points[2*s + 1][0];
vb[8*s + 5] = points[2*s + 1][1];
vb[8*s + 6] = 0.0f;
vb[8*s + 7] = 0.1f;
}

unsigned int* ib = static_cast<unsigned int*>(rtcSetNewGeometryBuffer(geom,
RTC_BUFFER_TYPE_INDEX, 0, RTC_FORMAT_UINT, sizeof(unsigned int), segmentsCount));

for(std::size_t s = 0 ; s < segmentsCount ; ++s)
ib[s] = 2*s;

rtcCommitGeometry(geom);
error = rtcGetDeviceError(device);
if(error != RTC_ERROR_NONE)
throw std::runtime_error("failed to commit embree geometry: " + translateEmbreeError(error));

rtcAttachGeometry(scene, geom);
error = rtcGetDeviceError(device);
if(error != RTC_ERROR_NONE)
throw std::runtime_error("failed to attach embree geometry: " + translateEmbreeError(error));

rtcReleaseGeometry(geom);
error = rtcGetDeviceError(device);
if(error != RTC_ERROR_NONE)
throw std::runtime_error("failed to release embree geoemtry: " + translateEmbreeError(error));

rtcCommitScene(scene);
error = rtcGetDeviceError(device);
if(error != RTC_ERROR_NONE)
throw std::runtime_error("failed to commit embree scene: " + translateEmbreeError(error));
 
RTCRayHit rayHit;
rayHit.ray.org_x = 0.5f; rayHit.ray.org_y = 1.0f; rayHit.ray.org_z = 0.0f;
rayHit.ray.dir_x = 0.0f; rayHit.ray.dir_y = -1.0f; rayHit.ray.dir_z = 0.0f;
rayHit.ray.tnear = 0.0f;
rayHit.ray.tfar = std::numeric_limits<float>::infinity();
rayHit.hit.geomID = RTC_INVALID_GEOMETRY_ID;
 
unsigned int facetToSkip = 3000;

RayQueryContext context;
context.skipFacet = facetToSkip;
rtcInitRayQueryContext(&context.context);

RTCIntersectArguments args;
rtcInitIntersectArguments(&args);
args.context = &context.context;
args.filter = intersectionFilter;
 
rtcIntersect1(scene, &rayHit, &args);
if(rayHit.hit.geomID == RTC_INVALID_GEOMETRY_ID)
throw std::runtime_error("You did not intersect while you should ?");

rtcReleaseScene(scene);
error = rtcGetDeviceError(device);
if(error != RTC_ERROR_NONE)
std::cerr << "failed to delete embree scene: " + translateEmbreeError(error) << std::endl;

rtcReleaseDevice(device);

return 0;
}

void intersectionFilter(const RTCFilterFunctionNArguments* args)
{
//When Using rtcIntersect1, only one ray to filter
RTCHit* pHit = reinterpret_cast<RTCHit*>(args->hit);
RayQueryContext* context = reinterpret_cast<RayQueryContext*>(args->context);

unsigned int skipFacetUInt = context->skipFacet;

if(pHit->primID == skipFacetUInt)
args->valid[0] = 0;
else
args->valid[0] = -1;
}
 

 

0 Kudos
1 Reply
SvenW_Intel
Moderator

Please initialize all rayHit.ray members, in particular rayHit.ray.mask = -1 should be set, otherwise ray mask is likely 0 and no geometry will be hit.

0 Kudos
Reply