I'm trying to do a bilinear normals interpolation on a heightmap and wrote this sort of code:
vec3 HeightMap::GetNormal( float X, float Y ) const
{
int I;
int J;
float FracI;
float FracJ;
WorldToData( X, Y, I, J, FracI, FracJ ); // transforms world X, Y into heightmap integer coords I, J and their fractional parts
vec3 Normal0 = GetDataNormal( I, J );
vec3 Normal1 = GetDataNormal( I, J+1 );
vec3 Normal2 = GetDataNormal( I+1, J );
vec3 Normal3 = GetDataNormal( I+1, J+1 );
if ( FracI + FracJ >= 1 ) Normal0 = Normal3;
// bilinear interpolation
vec3 Edge1 = Normal0 + (Normal1-Normal0) * FracJ;
vec3 Hypot = Normal2 + (Normal1-Normal2) * FracJ;
vec3 Normal = Edge1 + (Hypot - Edge1) * FracI;
return Normal.GetNormalized();
}
Helper function:
vec3 HeightMap::GetDataNormal( int I, int J ) const
{
// find heights
vec3 H0 = DataToWorld( I, J ); // returns X,Y,Z world coordinates of the point
vec3 H1 = DataToWorld( I, J+1 ); // for simplicity consider this I, J, Height(I,J)
vec3 H2 = DataToWorld( I+1, J ); // but actualy some scaling is done
vec3 Edge1 = H0-H2;
vec3 Edge2 = H0-H1;
vec3 Normal = ( Edge2.Cross( Edge1 ) ).GetNormalized();
if ( Normal.Z < 0 ) Normal *= -1.0f;
return Normal;
}
The normals for integer values of X and Y are ok, but as soon as i try to supply float coordinates to GetNormal() the result is wrong. :(
What could be wrong with this code?