I am working on a ray tracer and I got around to adding cylinders to the scene. The point I am stuck at is finding the surface normal vector in the point the ray hits. I need this to be able to do the diffuse lighting. What I have at this point is the 3d point where the camera ray hits the cylinder and the actual cylinder which is defined with a point on the central axis, the vector representing the direction of the axis and the radius. So to sum up my question, how do I find the normal vector in a point having the cylinder hit point, the radius, a point on its axis and the direction vector of the axis?
How can I compute normal on the surface of a cylinder?
Asked Answered
Are you using Unity? Or what language? –
Admissible
I am using C but in this context it should be irrelevant –
Unstick
Well, some languages might have a built-in function that could be useful. –
Admissible
Fair enough :) but I am stuck in good old C :)) –
Unstick
The cylinder normal vector starts at the centerline of the cylinder at the same z-height of the point where the ray intersects the cylinder, ends at the radial point of intersection. Normalize it and you have your unit normal vector.
If the cylinder centerline is not along the global z-direction of the scene you'll have to transform to cylinder coordinates, calculate the normal vector, and transform that back to global coordinates.
So basically I just compute the normal as if the cylinder was perfectly vertical then just use a rotation matrix on said vector to rotate it at the angle of the cylinder? –
Unstick
No need for "basically". Normal vector in cylinder coordinates; transform to global coordinates. Might be several rotations in sequence. –
Tandie
Worked like a charm :) Thanks for the help! –
Unstick
There are three possible situations:
- the hit_pt is on the TOP CAP of the cylinder:
if (length(hit_pt - cy.top_center) < cy.radius)
surface_normal = cy.ori;
- the hit_pt is on the BOTTOM CAP of the cylinder:
if (length(hit_pt - cy.bottom_center) < cy.radius)
surface_normal = -1 * cy.ori;
- the hit_pt is on the SIDE of the cylinder. We can use dot product to find the point 'pt' on the center line of the cylinder, so that the vector (hit_pt - pt) is orthogonal to the cylinder's orientation.
t = dot((hit_pt - cy.bottom_center), cy.ori); // cy.ori should be normalized and so has the length of 1.
pt = cy.bottom_center + t * cy.ori;
surface_normal = normalize(hit_pt - pt)));
© 2022 - 2024 — McMap. All rights reserved.