// from Sphere.hxx (InfinitePlane.hxx)
Vec3f GetNormal(Ray &ray)
{
Vec3f normal = Vec3f(ray.org + ray.t * ray.dir - center);
Normalize(normal);
if (bumpMap) {
Vec3f point = ray.org + ray.t * ray.dir;
// 2 vectors perpendicular to normal and to each other
Vec3f s1, s2;
double MIN_DOUBLE = 0.0001;
if (fabs(normal.z()) >MIN_DOUBLE)
s1 = Vec3f(-1, 1, (normal.x()-normal.y()) / normal.z() );
else if (fabs(normal.y()) > MIN_DOUBLE)
s1 = Vec3f(-1, (normal.x()-normal.z()) / normal.y(), 1);
else // y and z are 0
s1 = Vec3f(0, 0, 1);
s2 = normal.cross(s1);
Normalize(s1);
Normalize(s2);
// distance in which we compare colors
double delta = 0.01;
double grad, grad2;
Vec3f p1 = point+s1*delta;
Vec3f p2 = point-s1*delta;
Vec3f p3 = point+s2*delta;
Vec3f p4 = point-s2*delta;
// compute colors around our point to find out new normal
Vec3f color1 = shader->GetColor(0, 0, p1, this);
Vec3f color2 = shader->GetColor(0, 0, p2, this);
Vec3f color3 = shader->GetColor(0, 0, p3, this);
Vec3f color4 = shader->GetColor(0, 0, p4, this);
// gradient of color in direction s1, s2 through the point
grad = getYFromYCbCr(color1) - getYFromYCbCr(color2);
grad2 = getYFromYCbCr(color3) - getYFromYCbCr(color4);
// change vectors according to gradients
s1 += grad * normal;
s2 += grad2 * normal;
// new normal vector is perpendicular to changed s1, s2
Vec3f newNormal = s1.cross(s2);
// check if we dont got opposite vector from vector product
if ( fabs(acos( normal.dot(newNormal) / (normal.length()*newNormal.length()))) > M_PI/2 )
newNormal = - newNormal;
Normalize(newNormal);
return newNormal;
}
return normal;
};