bool Triangle::Intersect(const Ray &ray, float *tHit, float *rayEpsilon, DifferentialGeometry *dg) const { PBRT_RAY_TRIANGLE_INTERSECTION_TEST(const_cast<Ray *>(&ray), const_cast<Triangle *>(this)); // Compute $\VEC{s}_1$ // Get triangle vertices in _p1_, _p2_, and _p3_ const Point &p1 = mesh->p[v[0]]; const Point &p2 = mesh->p[v[1]]; const Point &p3 = mesh->p[v[2]]; Vector e1 = p2 - p1; Vector e2 = p3 - p1; Vector s1 = Cross(ray.d, e2); float divisor = Dot(s1, e1); if (divisor == 0.) return false; float invDivisor = 1.f / divisor; // Compute first barycentric coordinate Vector d = ray.o - p1; float b1 = Dot(d, s1) * invDivisor; if (b1 < 0. || b1 > 1.) return false; // Compute second barycentric coordinate Vector s2 = Cross(d, e1); float b2 = Dot(ray.d, s2) * invDivisor; if (b2 < 0. || b1 + b2 > 1.) return false; // Compute _t_ to intersection point float t = Dot(e2, s2) * invDivisor; if (t < ray.mint || t > ray.maxt) return false; // Compute triangle partial derivatives Vector dpdu, dpdv; float uvs[3][2]; GetUVs(uvs); // Compute deltas for triangle partial derivatives float du1 = uvs[0][0] - uvs[2][0]; float du2 = uvs[1][0] - uvs[2][0]; float dv1 = uvs[0][1] - uvs[2][1]; float dv2 = uvs[1][1] - uvs[2][1]; Vector dp1 = p1 - p3, dp2 = p2 - p3; float determinant = du1 * dv2 - dv1 * du2; if (determinant == 0.f) { // Handle zero determinant for triangle partial derivative matrix CoordinateSystem(Normalize(Cross(e2, e1)), &dpdu, &dpdv); } else { float invdet = 1.f / determinant; dpdu = ( dv2 * dp1 - dv1 * dp2) * invdet; dpdv = (-du2 * dp1 + du1 * dp2) * invdet; } // Interpolate $(u,v)$ triangle parametric coordinates float b0 = 1 - b1 - b2; float tu = b0*uvs[0][0] + b1*uvs[1][0] + b2*uvs[2][0]; float tv = b0*uvs[0][1] + b1*uvs[1][1] + b2*uvs[2][1]; // Test intersection against alpha texture, if present if (ray.depth != -1) { if (mesh->alphaTexture) { DifferentialGeometry dgLocal(ray(t), dpdu, dpdv, Normal(0,0,0), Normal(0,0,0), tu, tv, this); if (mesh->alphaTexture->Evaluate(dgLocal) == 0.f) return false; } } // Fill in _DifferentialGeometry_ from triangle hit *dg = DifferentialGeometry(ray(t), dpdu, dpdv, Normal(0,0,0), Normal(0,0,0), tu, tv, this); *tHit = t; *rayEpsilon = 1e-3f * *tHit; PBRT_RAY_TRIANGLE_INTERSECTION_HIT(const_cast<Ray *>(&ray), t); return true; }
bool Heightfield2::TriangleIntersect(const Ray &ray, float *tHit, float *rayEpsilon, DifferentialGeometry *dg, int index[]) const{ PBRT_RAY_TRIANGLE_INTERSECTION_TEST(const_cast<Ray *>(&ray), const_cast<Triangle *>(this)); // Get triangle vertices in _p1_, _p2_, and _p3_ const Point &p1o = point[index[0]]; const Point &p2o = point[index[1]]; const Point &p3o = point[index[2]]; const Point &p1 = (*ObjectToWorld)(p1o); const Point &p2 = (*ObjectToWorld)(p2o); const Point &p3 = (*ObjectToWorld)(p3o); Vector e1 = p2 - p1; Vector e2 = p3 - p1; Vector s1 = Cross(ray.d, e2); float divisor = Dot(s1, e1); if (divisor == 0.) return false; float invDivisor = 1.f / divisor; // Compute first barycentric coordinate Vector s = ray.o - p1; float b1 = Dot(s, s1) * invDivisor; if (b1 < 0. || b1 > 1.) return false; // Compute second barycentric coordinate Vector s2 = Cross(s, e1); float b2 = Dot(ray.d, s2) * invDivisor; if (b2 < 0. || b1 + b2 > 1.) return false; // Compute _t_ to intersection point float t = Dot(e2, s2) * invDivisor; if (t < ray.mint || t > ray.maxt) return false; // Compute triangle partial derivatives Vector dpdu, dpdv; // Compute deltas for triangle partial derivatives float du1 = p1o.x - p3o.x; float du2 = p2o.x - p3o.x; float dv1 = p1o.y - p3o.y; float dv2 = p2o.y - p3o.y; Vector dp1 = p1 - p3, dp2 = p2 - p3; float determinant = du1 * dv2 - dv1 * du2; if (determinant == 0.f) { // Handle zero determinant for triangle partial derivative matrix CoordinateSystem(Normalize(Cross(e2, e1)), &dpdu, &dpdv); } else { float invdet = 1.f / determinant; dpdu = ( dv2 * dp1 - dv1 * dp2) * invdet; dpdv = (-du2 * dp1 + du1 * dp2) * invdet; } // Interpolate $(u,v)$ triangle parametric coordinates float b0 = 1 - b1 - b2; float tu = b0*p1o.x + b1*p2o.x + b2*p3o.x; float tv = b0*p1o.y + b1*p2o.y + b2*p3o.y; // Fill in _DifferentialGeometry_ from triangle hit *dg = DifferentialGeometry(ray(t), dpdu, dpdv, Normal(0,0,0), Normal(0,0,0), tu, tv, this); *tHit = t; *rayEpsilon = 1e-3f * *tHit; ray.maxt = t; PBRT_RAY_TRIANGLE_INTERSECTION_HIT(const_cast<Ray *>(&ray), t); return true; }