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?
Asked
Active
Viewed 9,842 times
5
-
Are you using Unity? Or what language? – AMACB Mar 28 '16 at 16:26
-
I am using C but in this context it should be irrelevant – Rpreda Mar 28 '16 at 17:37
-
Well, some languages might have a built-in function that could be useful. – AMACB Mar 28 '16 at 17:40
-
1Fair enough :) but I am stuck in good old C :)) – Rpreda Mar 28 '16 at 17:45
2 Answers
5
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.

duffymo
- 305,152
- 44
- 369
- 561
-
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? – Rpreda Mar 28 '16 at 17:35
-
No need for "basically". Normal vector in cylinder coordinates; transform to global coordinates. Might be several rotations in sequence. – duffymo Mar 28 '16 at 18:39
-
2
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)));

tyuan
- 21
- 1