public virtual double Pdf(Point p, Vector wi) { // Intersect sample ray with area light geometry DifferentialGeometry dgLight; Ray ray = new Ray(p, wi, 1e-3d); ray.depth = -1; // temporary hack to ignore alpha mask double thit, rayEpsilon; if (!Intersect(ray, out thit, out rayEpsilon, out dgLight)) return 0.0d; // Convert light sample weight to solid angle measure double pdf = Geometry.DistanceSquared(p, ray.GetPointAt(thit)) / ( Geometry.AbsDot(dgLight.nn, -wi) * Area()); if (Double.IsInfinity(pdf)) pdf = 0.0d; return pdf; }
public override bool IntersectP(Ray r) { // Compute $\VEC{s}_1$ // Get triangle vertices in _p1_, _p2_, and _p3_ Point p1 = mesh.p[v[0]]; Point p2 = mesh.p[v[1]]; Point p3 = mesh.p[v[2]]; Vector e1 = p2 - p1; Vector e2 = p3 - p1; Vector s1 = Geometry.Cross(r.d, e2); double divisor = Geometry.Dot(s1, e1); if (divisor == 0.0d) return false; double invDivisor = 1.0d / divisor; // Compute first barycentric coordinate Vector d = r.o - p1; double b1 = Geometry.Dot(d, s1) * invDivisor; if (b1 < 0.0d || b1 > 1.0d) return false; // Compute second barycentric coordinate Vector s2 = Geometry.Cross(d, e1); double b2 = Geometry.Dot(r.d, s2) * invDivisor; if (b2 < 0.0d || b1 + b2 > 1.0d) return false; // Compute _t_ to intersection point double t = Geometry.Dot(e2, s2) * invDivisor; if (t < r.mint || t > r.maxt) return false; // Test shadow r intersection against alpha texture, if present if (r.depth != -1 && mesh.alphaTexture != null) { // Compute triangle partial derivatives Vector dpdu, dpdv; double[,] uvs = new double[3, 2]; GetUVs(uvs); // Compute deltas for triangle partial derivatives double du1 = uvs[0, 0] - uvs[2, 0]; double du2 = uvs[1, 0] - uvs[2, 0]; double dv1 = uvs[0, 1] - uvs[2, 1]; double dv2 = uvs[1, 1] - uvs[2, 1]; Vector dp1 = p1 - p3, dp2 = p2 - p3; double determinant = du1 * dv2 - dv1 * du2; if (determinant == 0.0d) { // Handle zero determinant for triangle partial derivative matrix Geometry.CoordinateSystem(Geometry.Normalize(Geometry.Cross(e2, e1)), out dpdu, out dpdv); } else { double invdet = 1.0d / determinant; dpdu = (dv2 * dp1 - dv1 * dp2) * invdet; dpdv = (-du2 * dp1 + du1 * dp2) * invdet; } // Interpolate $(u,v)$ triangle parametric coordinates double b0 = 1 - b1 - b2; double tu = b0 * uvs[0, 0] + b1 * uvs[1, 0] + b2 * uvs[2, 0]; double tv = b0 * uvs[0, 1] + b1 * uvs[1, 1] + b2 * uvs[2, 1]; DifferentialGeometry dgLocal = new DifferentialGeometry(r.GetPointAt(t), dpdu, dpdv, new Normal(0, 0, 0), new Normal(0, 0, 0), tu, tv, this); if (mesh.alphaTexture.Evaluate(dgLocal) == 0.0d) return false; } return true; }
public override Point Sample(Point p, double u1, double u2, ref Normal ns) { // Compute coordinate system for sphere sampling Point Pcenter = ObjectToWorld.Apply(new Point(0, 0, 0)); Vector wc = Geometry.Normalize(Pcenter - p); Vector wcX, wcY; Geometry.CoordinateSystem(wc, out wcX, out wcY); // Sample uniformly on sphere if $\pt{}$ is inside it if (Geometry.DistanceSquared(p, Pcenter) - radius * radius < 1e-4f) return Sample(u1, u2, ref ns); // Sample sphere uniformly inside subtended cone double sinThetaMax2 = radius * radius / Geometry.DistanceSquared(p, Pcenter); double cosThetaMax = Math.Sqrt(Math.Max(0.0d, 1.0d - sinThetaMax2)); DifferentialGeometry dgSphere; double thit, rayEpsilon; Point ps; Ray r = new Ray(p, MonteCarlo.UniformSampleCone(u1, u2, cosThetaMax, wcX, wcY, wc), 1e-3d); if (!Intersect(r, out thit, out rayEpsilon, out dgSphere)) thit = Geometry.Dot(Pcenter - p, Geometry.Normalize(r.d)); ps = r.GetPointAt(thit); ns = new Normal(Geometry.Normalize(ps - Pcenter)); if (ReverseOrientation) ns *= -1.0d; return ps; }