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}
)