If a point (x#,y#,z#) lies somewhere on a triangle (A,B,C), and the three triangle vertices all have different normals, how do you interpolate what the normal should be at the point in question?
Point=x,y,z
Triangle=
Ax,Ay,Az
Bx,By,Bz
Cx,Cy,Cz
Anx,Any,Anz
Bnx,Bny,Bnz
Cnx,Cny,Cnz
What should the normal be at the point (x,y,z)?
Let me guess, your getting banding when calculating shadows on curved surfaces? I suspect this is what you're after:
http://astronomy.swin.edu.au/~pbourke/raytracing/interpolation/
In other words:
1. Calculate the normals at the endpoints of each scanline of the polygon by linearly interpolating the vertex normals across the polygon edges.
2. Then linearly interpolate the normals at the end of each scanline across the scanline.
3. You will also need to normalize the resulting normal at the end of each scanline and at the point in the polygon.
Great summary sswift!
I also found Paul Bourke's coverage nicely illustrated, and informative.
Wayne:
I found it confusing, that's why I summarized it after I figured out what it was doing. :-)
I wouldn't have thought that linear interpolation would produce correct results. It probably doesn't, especially when perspective is involved, but I guess it's close enough for most purpouses.
Once the smooth normals at the vertices have been calculated, we can approximate the smooth normal at any point on the mesh by linear interpolation. This means that for a point P belonging to triangle T, the smooth normal at P is the weighted average of the smooth normals at the three vertices of T. The weighting factors may be calculated using scanline methods or by considering sub-triangle areas (described below). Finally, the interpolated smooth normal is used for lighting calculations.
An elegant way of calculating the weighting values for interpolation involves joining the point to the three vertices of the triangle it belongs to with straight lines. This divides the triangle into three small triangles. Now we use the area of a small triangle, divided by the total area of the triangle, as the weighting value for the smooth normal at the opposite vertex. This method is good for interpolating other quantities like colour across a triangle as well, but not textures.
I took a shot at coding the elegant way.
This is untested virgin code.
Here it is Josh, just for you.. 8)
Point=x,y,z
Triangle=
Ax,Ay,Az
Bx,By,Bz
Cx,Cy,Cz
Anx,Any,Anz
Bnx,Bny,Bnz
Cnx,Cny,Cnz
;---------------------------------------------------------
; Calculate Normal for point=x,y,z
; Calculate the total area, and that of each sub triangle
AreaT#=TriArea(Ax#,Ay#,Az#,Bx#,By#,Bz#,Cx#,Cy#,Cz#)
AreaB#=TriArea(Ax#,Ay#,Az#,x#,y#,z#,Cx#,Cy#,Cz#)
AreaC#=TriArea(Ax#,Ay#,Az#,x#,y#,z#,Bx#,By#,Bz#)
AreaA#=AreaT-AreaB-AreaC
; Calculate coefficients
c1#=AreaA#/AreaT#
c2#=AreaB#/AreaT#
c3#=AreaC#/AreaT#
; Calculate the new weighted normal
nx#=Anx#*c1+Bnx#*c2+Cnx#*c3
ny#=Any#*c1+Bny#*c2+Cny#*c3
nz#=Anz#*c1+Bnz#*c2+Cnz#*c3
;----------------------------------------------------
; Calculate area of triangle using Heron's Formula
Function TriArea(Ax#,Ay#,Az#,Bx#,By#,Bz#,Cx#,Cy#,Cz#)
; Calculate the side lengths
a#=sqr((Ax-Bx)^2+(Ay-By)^2+(Az-Bz)^2))
b#=sqr((Ax-Cx)^2+(Ay-Cy)^2+(Az-Cz)^2))
c#=sqr((Bx-Cx)^2+(By-Cy)^2+(Bz-Cz)^2))
; Calculate half the perimeter
s#=(1/2)*(a+b+c)
; Calculate total Area
Area#=sqr(s*(s-1)*(s-b)*s-c)
Return Area#
End function