Embree in progress

Hi Guys

I am working on making CPU raycasting within VTK using Embree,

The code below works great now. What would be the best way to “steal” vertexBuffers and indexBuffers. I am thinking the capability to do real-time raycasting from the normals of the input to a fixed mesh registered by the module. Also, I would like to make such that if TBB is the backend Embree is used and if not, the vtkOctree and a bit slower but reasonably fast locater is used from VTK.

Perhaps, this could be a nice way of contributing to the community.

#include <vtkCellArray.h>
#include <vtkPolyData.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkSmartPointer.h>
#include <vtkTriangle.h>

#include <embree3/rtcore.h>

int main(int, char*[])
{

  // Create a triangle
  vtkNew<vtkPoints> points;
  points->InsertNextPoint(-1.0, -1.0, 0.0);
  points->InsertNextPoint(1.0, 0.0, 0.0);
  points->InsertNextPoint(0.0, 1.0, 0.0);

  vtkNew<vtkTriangle> triangle;
  triangle->GetPointIds()->SetId(0, 0);
  triangle->GetPointIds()->SetId(1, 1);
  triangle->GetPointIds()->SetId(2, 2);

  vtkNew<vtkCellArray> triangles;
  triangles->InsertNextCell(triangle);

  // Create a polydata object
  vtkNew<vtkPolyData> trianglePolyData;

  // Add the geometry and topology to the polydata
  trianglePolyData->SetPoints(points);
  trianglePolyData->SetPolys(triangles);

  int numberOfFaces = trianglePolyData->GetNumberOfCells();
  std::cout << "nFaces: " << numberOfFaces << std::endl;

  vtkPoints* points0 = trianglePolyData->GetPoints();
  vtkDataArray* vertices = points0->GetData();

  RTCDevice device;
  RTCScene scene;

  static const char config[] = "frequency_level=simd128";
  device = rtcNewDevice(config);
  scene   = rtcNewScene(device);

  RTCGeometry geom = rtcNewGeometry(device, RTC_GEOMETRY_TYPE_TRIANGLE);

  rtcSetSharedGeometryBuffer(geom,
			     RTC_BUFFER_TYPE_VERTEX,
			     0, /* slot */
			     RTC_FORMAT_FLOAT3,
			     (void*) vertices->GetVoidPointer(0),
			     0, /* byteOffset */
			     3*sizeof(float), /* stride */
			     3*numberOfFaces);

  for (int i = 0 ; i < 3 ; i++) {
    std::cout << "Point " << i << ": " <<
      *(static_cast<float*>(vertices->GetVoidPointer(0)) + i*3 + 0) << ", " <<
      *(static_cast<float*>(vertices->GetVoidPointer(0)) + i*3 + 1) << ", " <<
      *(static_cast<float*>(vertices->GetVoidPointer(0)) + i*3 + 2) << std::endl;
  }

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

  for( int i = 0; i < numberOfFaces; i++) {
    vtkSmartPointer<vtkIdList> face = vtkSmartPointer<vtkIdList>::New();
    trianglePolyData->GetCellPoints(i,face);
    ib[i*3 + 0] = (unsigned) face->GetId(0);
    ib[i*3 + 1] = (unsigned) face->GetId(1);
    ib[i*3 + 2] = (unsigned) face->GetId(2);
  }

  rtcCommitGeometry(geom);
  rtcAttachGeometry(scene, geom);
  rtcReleaseGeometry(geom);
  rtcCommitScene(scene);

  RTCRayHit rayhit; 
  rayhit.ray.org_x  = 0.f; rayhit.ray.org_y = 0.f; rayhit.ray.org_z = -1.f;
  rayhit.ray.dir_x  = 0.f; rayhit.ray.dir_y = 0.f; rayhit.ray.dir_z =  1.f;
  rayhit.ray.tnear  = 0.f;
  rayhit.ray.tfar   = std::numeric_limits<float>::infinity();
  rayhit.hit.geomID = RTC_INVALID_GEOMETRY_ID;
  // This made it work with embree3. With embree4 it works without this
  rayhit.hit.instID[0] = RTC_INVALID_GEOMETRY_ID;
  rayhit.ray.mask = -1;
  rayhit.ray.flags = 0;
  // End of fix

  RTCIntersectContext context;
  rtcInitIntersectContext(&context);

  rtcIntersect1(scene, &context, &rayhit);

  if (rayhit.hit.geomID != RTC_INVALID_GEOMETRY_ID) {
    std::cout << "Intersection at t = " << rayhit.ray.tfar << std::endl;
  } else {
    std::cout << "No Intersection" << std::endl;
  }

  rtcReleaseScene(scene);
  rtcReleaseDevice(device);  
  
  return EXIT_SUCCESS;
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.10)

project(raytrace
  LANGUAGES CXX
  VERSION 1.0.0.0)

if(CMAKE_SIZEOF_VOID_P EQUAL 8)
  set(CMAKE_POSITION_INDEPENDENT_CODE ON)
endif()

find_package(EMBREE 3.13.5 QUIET)

find_package(VTK COMPONENTS 
  CommonColor
  CommonCore
  CommonDataModel
  InteractionStyle
  RenderingContextOpenGL2
  RenderingCore
  RenderingFreeType
  RenderingGL2PSOpenGL2
  RenderingOpenGL2
)
 
add_executable(Discourse MACOSX_BUNDLE Discourse.cxx )
target_link_libraries(Discourse
  PRIVATE
  ${VTK_LIBRARIES}
  ${EMBREE_LIBRARIES}
)
target_include_directories(Discourse PRIVATE ${EMBREE_INCLUDE_DIR})

# Without this everything works
vtk_module_autoinit(
  TARGETS Discourse
  MODULES ${VTK_LIBRARIES}
)
1 Like

I managed to get it to work with embree4. With embree3, it worked by adding some extra options to the RTCRayHit structure.

  rayhit.hit.instID[0] = RTC_INVALID_GEOMETRY_ID;
  rayhit.ray.mask = -1;
  rayhit.ray.flags = 0;
1 Like