In the image above, I have put in red rectangle two pixels that are rendered black when they should not. I have made some debugging and found out that in those cases, the surface normal is pointing at the wrong direction. When I did n = -n the pixel gained its correct color (however If I do it for all pixels, all those correct will become wrong)
This is the code in which the surface normal is calculated. It is in the Triangle class (the torus is made of triangles - I import the model).
The calculation for the surface normal is at the top. Any ideas why the its direction is wrong? (it points at the opposite direction than it should).
override bool hit(const ref Ray r, float p0, float p1, ref HitInfo hitInfo)
{
// (e + td - a) . n = 0
// ... t(d.n) + e.n - a.n = 0
// we need to solve as t to find the solution
// t = (dot(a, n) - dot(e, n)) / dot(d, n);
// and because dot product is distributive,
// we can write t = dot(a-e,n) / dot(d,n)
Vector3 temp0 = b-a, temp1 = c-a;
Vector3 n = cross(temp0, temp1); // calculate the normal of the plane that the triangle is on
n.normalize();
// TODO: r.d may have to be normalized?
// if the normal and the ray are parallel, there's no intersection
float dDotN = dot(r.d, n);
// TODO: this might be causing accuracy problems. I should check it out
if( dDotN == 0 )
return false;
// find the intersection point P with the plane
const Vector3 aMinusR = a-r.e;
float t = dot(aMinusR, n) / dDotN;
Vector3 p = r.e + r.d * t;
// now we need to test if the point is inside the triangle
// 1) test if its in the negative subspace of vector ab
Vector3 ab = b-a;
Vector3 ap = p-a;
Vector3 c1 = cross(ab, ap);
c1.normalize();
Vector3 ac = c-a;
Vector3 c2 = cross(ab, ac);
c2.normalize();
immutable E = 0.01f;
if( abs(c1.x - c2.x) > E || abs(c1.y - c2.y) > E || abs(c1.z-c2.z) > E )
return false;
// 2) test if its in the negative subspace of vector bc
Vector3 bc = c-b;
Vector3 bp = p-b;
c1 = cross(bc, bp);
c1.normalize();
Vector3 ba = b-a;
c2 = cross(ba, bc);
c2.normalize();
if( abs(c1.x - c2.x) > E || abs(c1.y - c2.y) > E || abs(c1.z-c2.z) > E)
return false;
// 3) test if its in the negative subspace of vector ca
Vector3 ca = a-c;
Vector3 cp = p-c;
c1 = cross(ca, cp);
c1.normalize();
Vector3 cb = b-c;
c2 = cross(ca, cb);
c2.normalize();
if( abs(c1.x - c2.x) > E || abs(c1.y - c2.y) > E || abs(c1.z - c2.z) > E )
return false;
hitInfo.t = t;
hitInfo.hitPoint = p;
hitInfo.surfaceNormal = n;
hitInfo.hitSurface = this;
hitInfo.ray = r.d;
//import std.stdio;
//writeln("in triangle hit");
return true;
}