Hi, I am trying to count the number of triangles that share a common edge in order to classify edges. The input mesh is assumed to be clean and may contain boundary edges, manifold edges, or non-manifold edges. In addition, I would also like to identify the IDs of the incident triangles when the edge is shared by exactly two triangles.
I am investigating whether the watertight ray-triangle intersection can be used for this purpose. Here is part of my test code:
// --- Case 1: ray hits the boundary edge of a single triangle (1 face) ---
printf("=== Case 1: single triangle, hit boundary edge ===\n");
{
RayMesh::TriangleMesh mesh;
mesh.vertices = {
make_float3(0.f, 0.f, 0.f),
make_float3(1.f, 0.f, 0.f),
make_float3(0.f, 1.f, 0.f),
};
mesh.indices = {0, 1, 2};
mesh.num_vertices = 3;
mesh.num_triangles = 1;
RayMesh::DeviceMesh d_mesh = RayMesh::OptixIndex::UploadToDevice(mesh);
RayMesh::OptixIndex index({makeProbeDescriptor()});
index.BuildAccel(d_mesh, build_opt);
// Shoot at edge (v0, v1) from slightly above the mesh
int hits = shootRay(index,
make_float3(0.5f, 0.f, 0.1f), // origin: near edge midpoint, above
make_float3(0.f, 0.f, -1.f), // direction: down toward edge
0.2f); // tmax
printf(" hits: %d\n\n", hits);
RayMesh::OptixIndex::FreeFromDevice(d_mesh);
}
// --- Case 2: ray hits the shared edge of two triangles (2 faces) ---
printf("=== Case 2: two triangles, hit shared edge ===\n");
{
RayMesh::TriangleMesh mesh;
mesh.vertices = {
make_float3(0.f, 0.f, 0.f), // v0
make_float3(1.f, 0.f, 0.f), // v1
make_float3(0.5f, 1.f, 0.f), // v2
make_float3(0.5f, 1.f, 0.5f), // v3
};
mesh.indices = {0, 1, 2, 0, 3, 1};
mesh.num_vertices = 4;
mesh.num_triangles = 2;
RayMesh::DeviceMesh d_mesh = RayMesh::OptixIndex::UploadToDevice(mesh);
RayMesh::OptixIndex index({makeProbeDescriptor()});
index.BuildAccel(d_mesh, build_opt);
// Shoot at shared edge (v0, v1) from slightly above
int hits = shootRay(index,
make_float3(0.5f, 0.f, 0.1f),
make_float3(0.f, 0.f, -1.f),
0.2f);
printf(" hits: %d\n\n", hits);
RayMesh::OptixIndex::FreeFromDevice(d_mesh);
}
// --- Case 3: ray hits the shared edge of three triangles (3 faces) ---
printf("=== Case 3: three triangles sharing one edge ===\n");
{
RayMesh::TriangleMesh mesh;
mesh.vertices = {
make_float3(0.f, 0.f, 0.f), // v0
make_float3(1.f, 0.f, 0.f), // v1
make_float3(0.5f, 1.f, 0.f), // v2
make_float3(0.5f, 1.f, -0.5f), // v3
make_float3(0.5f, 1.f, -0.5f), // v4
};
mesh.indices = {0, 2, 1, 0, 1, 3, 0, 4, 1};
mesh.num_vertices = 5;
mesh.num_triangles = 3;
RayMesh::DeviceMesh d_mesh = RayMesh::OptixIndex::UploadToDevice(mesh);
RayMesh::OptixIndex index({makeProbeDescriptor()});
index.BuildAccel(d_mesh, build_opt);
// Shoot at shared edge (v0, v1) from slightly above
int hits = shootRay(index,
make_float3(0.5f, 0.01f, 0.1f),
make_float3(0.f, 0.f, -1.f),
0.2f);
printf(" hits: %d\n\n", hits);
RayMesh::OptixIndex::FreeFromDevice(d_mesh);
}
There is the output and for different triangle arrangement the hit count is different:
=== Case 1: single triangle, hit boundary edge ===
[2026-06-03 16:20:21.958] [info] Enable timing
Hit pridIdx = 0
hits: 1
=== Case 2: two triangles, hit shared edge ===
[2026-06-03 16:20:22.045] [info] Enable timing
Hit pridIdx = 1
Hit pridIdx = 0
hits: 2
=== Case 3: three triangles sharing one edge ===
[2026-06-03 16:20:22.126] [info] Enable timing
Hit pridIdx = 1
Hit pridIdx = 2
Hit pridIdx = 0
hits: 3
Done.