Original Post
I'm working on adding triangles to my raytracer, it currently does planes and spheres including shading, shadows, and ambient occlusion. I've developed the code below to determine a ray's intersection point with an arbitrary triangle. Although the raw intersection is correct, the shading is wrong and a triangle will appear in-front of all other objects even when behind them. I think it's because the ray parameter 't' is getting calculated wrong, but I can't seem to figure out where. Any help is appreciated. The attached image is of a leaning-back triangle intersecting a vertical plane, as can('t) be seen, the part of the triangle behind the plane is still visible. I can provide other renders or the file I use to generate the scene if desired. The constructor for the Triangle and the hit function are copied below Triangle::Triangle(const Point3D& a, const Point3D& b, const Point3D& c) :GeometricObject(), t1(a), t2(b), t3(c) { // t1, t2, and t3 are the verticies of the triangle // Subtract points to get two sides of the triangle Vector3D v1 = t2 - t1; Vector3D v2 = t3 - t2; // ^ is cross product operator // use cross product to get the normal for the triangle n = v1 ^ v2; n.normalize(); // * is dot-product when used on vectors or anything // based on a vector (Normal, Ray) d = t1 * n; } bool Triangle::hit(const Ray& ray, double& tmin, ShadeRec& sr) const{ // t = ray * n / // (p0 * n) + d float vd = ray * n; // Origin in vector form Vector3D p0(-Vector3D(ray.o)); // Ray is parallel to triangle's plane if (vd == 0) return false; // Triangle's normal faces away from ray origin if (vd > 0) return false; float v0 = (p0 * n) + d; float t = vd / v0; // Intersection occurs before ray origin if (t < 0) return false; // ray-triangle intersection point Vector3D p(ray.o + t * ray); // Can be optimized, not for ease of debugging Vector3D v1 = t1 - p; Vector3D v2 = t2 - p; Vector3D v3 = t3 - p; Vector3D n1; // store the normal for the side float d1; // Check if the point is within the triangle // by checking which side of each edge it's on // Side 1 n1 = v2 ^ v1; n1.normalize(); d1 = p0 * n1; if (((p * n1) + d1) < 0) return false; // Side 2 n1 = v3 ^ v2; n1.normalize(); d1 = p0 * n1; if (((p * n1) + d1) < 0) return false; // Side 3 n1 = v1 ^ v3; n1.normalize(); d1 = p0 * n1; if (((p * n1) + d1) < 0) return false; // kEpsilon is a very small positive value // used to avoid shading errors due to // floating point precision if (t > kEpsilon) { tmin = t; sr.normal = n; sr.localHitPoint = ray.o + t * ray; return true; }else { return false; } }