lighttransport / nanort

NanoRT, single header only modern ray tracing kernel.
MIT License
1.07k stars 89 forks source link

Visible vertices computation #44

Closed blackccpie closed 5 years ago

blackccpie commented 5 years ago

Hi,

I'm looking for a lightweight library to compute visible vertices of a 3D model given camera pose. Sorry if my question may seem obvious, but I'm wondering if nanort is the right tool for that purpose, and if there are useful sample codes I can have a look at?

Thanks for your help,

Albert

syoyo commented 5 years ago

If you don't need precise visibility, things are rather easy to implement.

You can shoot rays as in ordinal ray tracing with orthographic or perspective camera, then mark the visibility for hit surface(face ID and vertex ID can be looked up using Trianglntersection::prim_id)

If you need precise visibility for a given camera pose, you need to implement something like this: https://www.cg.tuwien.ac.at/research/publications/2006/WONKA-2006-GVS/

or for more general situation: http://jcgt.org/published/0003/04/02/

blackccpie commented 5 years ago

@syoyo : thanks for these pointers, I'll have a look, and maybe get back to you if I still don't make it.

Regards

blackccpie commented 5 years ago

Hi @syoyo, I tried implementing your first solution (I don't need precise visibility), by casting rays to each triangle centroid on the target mesh. At first rays origin was set to the origin of the coordinate frame, and the result seemed consistent. But then I tried to set the rays origin elsewhere, and I started to have a lot of rays not hitting any face, which should not happen by design if the rays are oriented to target triangle centroids. I tried to reproduce the problem in a small sample code targetting only one of my mesh's triangle:

std::vector<float3> vertices = {
    { -0.0211979f, 0.1272f, 0.00915278f },
    { -0.0144471f, 0.128935f, 0.00903509f },
    { -0.0143059f, 0.128197f, 0.00333856f }
};
uint3 face = { 0, 1, 2 };

float3 face_center = {  vertices[0].x + vertices[1].x + vertices[2].x / 3.f,
                        vertices[0].y + vertices[1].y + vertices[2].y / 3.f,
                        vertices[0].z + vertices[1].z + vertices[2].z / 3.f };

nanort::BVHBuildOptions<float> options;
nanort::TriangleMesh<float> triangle_mesh( reinterpret_cast<float*>( vertices.data() ), reinterpret_cast<uint32_t*>( &face ), /* stride */sizeof(float) * 3 );
nanort::TriangleSAHPred<float> triangle_pred( reinterpret_cast<float*>( vertices.data() ), reinterpret_cast<uint32_t*>( &face ), /* stride */sizeof(float) * 3 );
nanort::BVHAccel<float> accel;
auto ret = accel.Build( 1, triangle_mesh, triangle_pred, options );
assert(ret);

nanort::BVHTraceOptions trace_options;
nanort::TriangleIntersection<float> isect;
nanort::TriangleIntersector<> triangle_intersector( reinterpret_cast<float*>( vertices.data() ), 
                                                    reinterpret_cast<uint32_t*>( &face ),
                                                    /* stride */sizeof(float) * 3 );

float3 cam_pos = { 0.f, 0.f, 0.f };

nanort::Ray<float> ray;
const float far = 1.e+30f;
ray.min_t = 0.f;
ray.max_t = far;
ray.org[0] = cam_pos.x;
ray.org[1] = cam_pos.y;
ray.org[2] = cam_pos.z;
float3 dir;
dir[0] = face_center.x - cam_pos.x;
dir[1] = face_center.y - cam_pos.y;
dir[2] = face_center.z - cam_pos.z;
dir.normalize();
ray.dir[0] = dir[0];
ray.dir[1] = dir[1];
ray.dir[2] = dir[2];

auto hit = accel.Traverse( ray, triangle_intersector, &isect, trace_options );
if( hit )
{
    std::cout << "hit!" << std::endl;
}
else
{
    std::cout << "no hit!" << std::endl;
}

If I execute this code, the face is hit, but if a set the camera pos to { 0.f, 0.f, 0.5f } for example, then I've got no hit. Could you help me finding out what I'm doing wrong?

Thx for your help

syoyo commented 5 years ago

You need parenthesis to compute face center.

float3 face_center = {  (vertices[0].x + vertices[1].x + vertices[2].x) / 3.f,
                        (vertices[0].y + vertices[1].y + vertices[2].y) / 3.f,
                        (vertices[0].z + vertices[1].z + vertices[2].z) / 3.f };
blackccpie commented 5 years ago

@syoyo : my mistake, thanks for the hint, now that works nicely.

Regards