in code/cpp/tools/generate_ray_intersections/main.cpp [27:228]
int main (int argc, const char** argv) {
//
// parse input arguments
//
args::ArgumentParser parser("generate_ray_intersections", "");
args::HelpFlag help (parser, "__DUMMY__", "Display this help menu", {'h', "help"});
args::ValueFlag<std::string> vertices_file_arg (parser, "VERTICES_FILE", "vertices_file", {"vertices_file"}, args::Options::Required);
args::ValueFlag<std::string> faces_file_arg (parser, "FACES_FILE", "faces_file", {"faces_file"}, args::Options::Required);
args::ValueFlag<std::string> ray_positions_file_arg (parser, "RAY_POSITIONS_FILE", "ray_positions_file", {"ray_positions_file"}, args::Options::Required);
args::ValueFlag<std::string> ray_directions_file_arg (parser, "RAY_DIRECTIONS_FILE", "ray_directions_file", {"ray_directions_file"}, args::Options::Required);
args::ValueFlag<std::string> output_ray_hit_data_float_file_arg (parser, "OUTPUT_RAY_HIT_DATA_FLOAT_FILE", "output_ray_hit_data_float_file", {"output_ray_hit_data_float_file"}, args::Options::Required);
args::ValueFlag<std::string> output_ray_hit_data_int_file_arg (parser, "OUTPUT_RAY_HIT_DATA_INT_FILE", "output_ray_hit_data_int_file", {"output_ray_hit_data_int_file"}, args::Options::Required);
args::Flag silent_arg (parser, "__DUMMY__", "silent", {"silent"});
try {
parser.ParseCLI(argc, argv);
} catch (args::Completion e) {
std::cout << parser;
return 1;
} catch (args::Help e) {
std::cout << parser;
return 1;
} catch (args::ParseError e) {
std::cout << parser;
std::cout << std::endl << std::endl << std::endl << e.what() << std::endl << std::endl << std::endl;
return 1;
} catch (args::RequiredError e) {
std::cout << parser;
std::cout << std::endl << std::endl << std::endl << e.what() << std::endl << std::endl << std::endl;
return 1;
}
auto vertices_file = args::get(vertices_file_arg);
auto faces_file = args::get(faces_file_arg);
auto ray_positions_file = args::get(ray_positions_file_arg);
auto ray_directions_file = args::get(ray_directions_file_arg);
auto output_ray_hit_data_float_file = args::get(output_ray_hit_data_float_file_arg);
auto output_ray_hit_data_int_file = args::get(output_ray_hit_data_int_file_arg);
auto silent = args::get(silent_arg);
arma::mat vertices, faces, ray_positions, ray_directions;
if (!silent) {
std::cout << "[HYPERSIM: GENERATE_RAY_INTERSECTIONS] Begin..." << std::endl;
}
//
// load input data
//
vertices.load(vertices_file, arma::hdf5_binary_trans);
faces.load(faces_file, arma::hdf5_binary_trans);
ray_positions.load(ray_positions_file, arma::hdf5_binary_trans);
ray_directions.load(ray_directions_file, arma::hdf5_binary_trans);
assert(vertices.n_cols == 3);
assert(faces.n_cols == 3);
assert(ray_positions.n_cols == 3);
assert(ray_directions.n_cols == 3);
assert(ray_positions.n_rows == ray_directions.n_rows);
if (!silent) {
std::cout << "[HYPERSIM: GENERATE_RAY_INTERSECTIONS] Tracing " << ray_positions.n_rows << " rays..." << std::endl;
}
//
// construct Embree data
//
assert(RTC_MAX_INSTANCE_LEVEL_COUNT == 1);
auto rtc_device = rtcNewDevice(nullptr);
assert(rtcGetDeviceError(nullptr) == RTC_ERROR_NONE);
auto rtc_scene = rtcNewScene(rtc_device);
assert(rtcGetDeviceError(rtc_device) == RTC_ERROR_NONE);
auto rtc_triangle_mesh = rtcNewGeometry(rtc_device, RTC_GEOMETRY_TYPE_TRIANGLE);
assert(rtcGetDeviceError(rtc_device) == RTC_ERROR_NONE);
// set vertices
auto rtc_vertices = (Vertex*) rtcSetNewGeometryBuffer(rtc_triangle_mesh, RTC_BUFFER_TYPE_VERTEX, 0, RTC_FORMAT_FLOAT3, sizeof(Vertex), vertices.n_rows);
assert(rtcGetDeviceError(rtc_device) == RTC_ERROR_NONE);
for (int i = 0; i < vertices.n_rows; i++) {
rtc_vertices[i].x = vertices(i,0);
rtc_vertices[i].y = vertices(i,1);
rtc_vertices[i].z = vertices(i,2);
}
// set triangles
auto rtc_triangles = (Triangle*) rtcSetNewGeometryBuffer(rtc_triangle_mesh, RTC_BUFFER_TYPE_INDEX, 0, RTC_FORMAT_UINT3, sizeof(Triangle), faces.n_rows);
assert(rtcGetDeviceError(rtc_device) == RTC_ERROR_NONE);
for (int i = 0; i < faces.n_rows; i++) {
rtc_triangles[i].v0 = faces(i,0);
rtc_triangles[i].v1 = faces(i,1);
rtc_triangles[i].v2 = faces(i,2);
}
rtcCommitGeometry(rtc_triangle_mesh);
assert(rtcGetDeviceError(rtc_device) == RTC_ERROR_NONE);
unsigned int geomID = rtcAttachGeometry(rtc_scene, rtc_triangle_mesh);
assert(rtcGetDeviceError(rtc_device) == RTC_ERROR_NONE);
rtcReleaseGeometry(rtc_triangle_mesh);
assert(rtcGetDeviceError(rtc_device) == RTC_ERROR_NONE);
rtcCommitScene(rtc_scene);
assert(rtcGetDeviceError(rtc_device) == RTC_ERROR_NONE);
RTCIntersectContext rtc_intersect_context;
rtcInitIntersectContext(&rtc_intersect_context);
assert(rtcGetDeviceError(rtc_device) == RTC_ERROR_NONE);
//
// perform raycasting
//
arma::mat ray_hit_data_float = arma::ones<arma::mat>(ray_positions.n_rows,4) * std::numeric_limits<float>::infinity();
arma::imat ray_hit_data_int = arma::ones<arma::imat>(ray_positions.n_rows,1) * -1;
for (int i = 0; i < ray_positions.n_rows; i++) {
// initialize ray
arma::vec ray_position = ray_positions.row(i).t();
arma::vec ray_direction_normalized = arma::normalise(ray_directions.row(i).t());
RTCRayHit rtc_ray_hit;
rtc_ray_hit.ray.org_x = (float)ray_position(0);
rtc_ray_hit.ray.org_y = (float)ray_position(1);
rtc_ray_hit.ray.org_z = (float)ray_position(2);
rtc_ray_hit.ray.dir_x = (float)ray_direction_normalized(0);
rtc_ray_hit.ray.dir_y = (float)ray_direction_normalized(1);
rtc_ray_hit.ray.dir_z = (float)ray_direction_normalized(2);
rtc_ray_hit.ray.tnear = 0.0f;
rtc_ray_hit.ray.tfar = std::numeric_limits<float>::infinity();
rtc_ray_hit.ray.time = 0.0f;
rtc_ray_hit.ray.mask = 0;
rtc_ray_hit.ray.id = 0;
rtc_ray_hit.ray.flags = 0;
rtc_ray_hit.hit.Ng_x = std::numeric_limits<float>::infinity();
rtc_ray_hit.hit.Ng_y = std::numeric_limits<float>::infinity();
rtc_ray_hit.hit.Ng_z = std::numeric_limits<float>::infinity();
rtc_ray_hit.hit.u = std::numeric_limits<float>::infinity();
rtc_ray_hit.hit.v = std::numeric_limits<float>::infinity();
rtc_ray_hit.hit.primID = RTC_INVALID_GEOMETRY_ID;
rtc_ray_hit.hit.geomID = RTC_INVALID_GEOMETRY_ID;
rtc_ray_hit.hit.instID[0] = RTC_INVALID_GEOMETRY_ID;
// intersect ray with scene
rtcIntersect1(rtc_scene, &rtc_intersect_context, &rtc_ray_hit);
if (rtc_ray_hit.ray.tfar < std::numeric_limits<float>::infinity()) {
assert(rtc_ray_hit.hit.primID != RTC_INVALID_GEOMETRY_ID);
assert(rtc_ray_hit.hit.geomID != RTC_INVALID_GEOMETRY_ID);
} else {
assert(rtc_ray_hit.hit.primID == RTC_INVALID_GEOMETRY_ID);
assert(rtc_ray_hit.hit.geomID == RTC_INVALID_GEOMETRY_ID);
}
if (rtc_ray_hit.hit.geomID != RTC_INVALID_GEOMETRY_ID) {
arma::vec ray_hit_normal_normalized = arma::normalise(arma::vec({rtc_ray_hit.hit.Ng_x, rtc_ray_hit.hit.Ng_y, rtc_ray_hit.hit.Ng_z}));
ray_hit_data_float(i, 0) = rtc_ray_hit.ray.tfar;
ray_hit_data_float(i, 1) = ray_hit_normal_normalized(0);
ray_hit_data_float(i, 2) = ray_hit_normal_normalized(1);
ray_hit_data_float(i, 3) = ray_hit_normal_normalized(2);
ray_hit_data_int(i, 0) = rtc_ray_hit.hit.primID;
}
}
//
// saving intersection distances
//
if (!silent) {
std::cout << "[HYPERSIM: GENERATE_RAY_INTERSECTIONS] Saving intersection data..." << std::endl;
}
ray_hit_data_float.save(output_ray_hit_data_float_file, arma::hdf5_binary_trans);
ray_hit_data_int.save(output_ray_hit_data_int_file, arma::hdf5_binary_trans);
//
// release Embree data
//
rtcReleaseScene(rtc_scene); rtc_scene = nullptr;
assert(rtcGetDeviceError(rtc_device) == RTC_ERROR_NONE);
rtcReleaseDevice(rtc_device); rtc_device = nullptr;
assert(rtcGetDeviceError(nullptr) == RTC_ERROR_NONE);
return 0;
}