public override bool Intersect(Ray r, Intersection isect) { Transform w2p; WorldToPrimitive.Interpolate(r.time, out w2p); Ray ray = w2p.Apply(r); if (!primitive.Intersect(ray, isect)) return false; r.maxt = ray.maxt; isect.primitiveId = primitiveId; if (!w2p.IsIdentity()) { // Compute world-to-object transformation for instance isect.WorldToObject = isect.WorldToObject * w2p; isect.ObjectToWorld = Transform.Inverse isect.WorldToObject.Inverse( // Transform instance's differential geometry to world space Transform PrimitiveToWorld = Inverse(w2p); isect->dg.p = PrimitiveToWorld(isect->dg.p); isect->dg.nn = Normalize(PrimitiveToWorld(isect->dg.nn)); isect->dg.dpdu = PrimitiveToWorld(isect->dg.dpdu); isect->dg.dpdv = PrimitiveToWorld(isect->dg.dpdv); isect->dg.dndu = PrimitiveToWorld(isect->dg.dndu); isect->dg.dndv = PrimitiveToWorld(isect->dg.dndv); } return true; }
public Ray(Point origin, Vector direction, Ray parent, double start, double end = double.PositiveInfinity) { this.o = origin; this.d = direction; this.mint = start; this.maxt = end; this.time = parent.time; this.depth = parent.depth + 1; }
public Ray Copy() { Ray _r = new Ray(); _r.o = this.o; _r.d = this.d; _r.mint = this.mint; _r.maxt = this.maxt; _r.time = this.time; _r.depth = this.depth; return _r; }
public override bool Intersect(Ray r, out double tHit, out double rayEpsilon, out DifferentialGeometry dg) { tHit = Double.NaN; rayEpsilon = Double.NaN; dg = null; // Transform _Ray_ to object space Ray ray = WorldToObject.Apply(r); // Compute plane intersection for disk if (Math.Abs(ray.d.z) < 1e-7) return false; double thit = (height - ray.o.z) / ray.d.z; if (thit < ray.mint || thit > ray.maxt) return false; // See if hit point is inside disk radii and $\phimax$ Point phit = ray.GetPointAt(thit); double dist2 = phit.x * phit.x + phit.y * phit.y; if (dist2 > radius * radius || dist2 < innerRadius * innerRadius) return false; // Test disk $\phi$ value against $\phimax$ double phi = Math.Atan2(phit.y, phit.x); if (phi < 0) phi += 2.0d * Math.PI; if (phi > phiMax) return false; // Find parametric representation of disk hit double u = phi / phiMax; double oneMinusV = ((Math.Sqrt(dist2) - innerRadius) / (radius - innerRadius)); double invOneMinusV = (oneMinusV > 0.0d) ? (1.0d / oneMinusV) : 0.0d; double v = 1.0d - oneMinusV; Vector dpdu = new Vector(-phiMax * phit.y, phiMax * phit.x, 0.0d); Vector dpdv = new Vector(-phit.x * invOneMinusV, -phit.y * invOneMinusV, 0.0d); dpdu *= phiMax * Constants.INV_TWOPI; dpdv *= (radius - innerRadius) / radius; Normal dndu = new Normal(0, 0, 0); Normal dndv = new Normal(0, 0, 0); // Initialize _DifferentialGeometry_ from parametric information Transform o2w = ObjectToWorld; dg = new DifferentialGeometry(o2w.Apply(phit), o2w.Apply(dpdu), o2w.Apply(dpdv), o2w.Apply(dndu), o2w.Apply(dndv), u, v, this); // Update _tHit_ for quadric intersection tHit = thit; // Compute _rayEpsilon_ for quadric intersection rayEpsilon = 5e-4d * tHit; return true; }
public override bool Intersect(Ray r, Intersection isect) { double thit, rayEpsilon; if (!shape.Intersect(r, out thit, out rayEpsilon, out isect.dg)) return false; isect.primitive = this; isect.WorldToObject = shape.WorldToObject; isect.ObjectToWorld = shape.ObjectToWorld; isect.shapeId = shape.shapeId; isect.primitiveId = primitiveId; isect.rayEpsilon = rayEpsilon; r.maxt = thit; return true; }
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 bool IntersectP(Ray r) { // Transform _Ray_ to object space Ray ray = WorldToObject.Apply(r); // Compute plane intersection for disk if (Math.Abs(ray.d.z) < 1e-7) return false; double thit = (height - ray.o.z) / ray.d.z; if (thit < ray.mint || thit > ray.maxt) return false; // See if hit point is inside disk radii and $\phimax$ Point phit = ray.GetPointAt(thit); double dist2 = phit.x * phit.x + phit.y * phit.y; if (dist2 > radius * radius || dist2 < innerRadius * innerRadius) return false; // Test disk $\phi$ value against $\phimax$ double phi = Math.Atan2(phit.y, phit.x); if (phi < 0) phi += 2.0d * Math.PI; if (phi > phiMax) return false; return true; }
public bool IntersectP(Ray ray, out double hitt0, out double hitt1) { hitt0 = hitt1 = double.PositiveInfinity; double t0 = ray.mint, t1 = ray.maxt; for (int i = 0; i < 3; ++i) { // Update interval for _i_th bounding box slab double invRayDir = 1.0d / ray.d[i]; double tNear = (pMin[i] - ray.o[i]) * invRayDir; double tFar = (pMax[i] - ray.o[i]) * invRayDir; // Update parametric interval from slab intersection $t$s if (tNear > tFar) Utility.Swap<double>(ref tNear, ref tFar); t0 = tNear > t0 ? tNear : t0; t1 = tFar < t1 ? tFar : t1; if (t0 > t1) return false; } hitt0 = t0; hitt1 = t1; return true; }
public abstract bool IntersectP(Ray r);
public override bool Intersect(Ray r, out double tHit, out double rayEpsilon, out DifferentialGeometry dg) { double phi, v; Point phit; tHit = Double.NaN; rayEpsilon = Double.NaN; dg = null; // Transform _Ray_ to object space Ray ray = WorldToObject.Apply(r); // Compute quadratic hyperboloid coefficients double A = a * ray.d.x * ray.d.x + a * ray.d.y * ray.d.y - c * ray.d.z * ray.d.z; double B = 2.0d * (a * ray.d.x * ray.o.x + a * ray.d.y * ray.o.y - c * ray.d.z * ray.o.z); double C = a * ray.o.x * ray.o.x + a * ray.o.y * ray.o.y - c * ray.o.z * ray.o.z - 1; // Solve quadratic equation for _t_ values double t0, t1; if (!Utility.Quadratic(A, B, C, out t0, out t1)) return false; // Compute intersection distance along ray if (t0 > ray.maxt || t1 < ray.mint) return false; double thit = t0; if (t0 < ray.mint) { thit = t1; if (thit > ray.maxt) return false; } // Compute hyperboloid inverse mapping phit = ray.GetPointAt(thit); v = (phit.z - p1.z) / (p2.z - p1.z); Point pr = (1.0d - v) * p1 + v * p2; phi = Math.Atan2(pr.x * phit.y - phit.x * pr.y, phit.x * pr.x + phit.y * pr.y); if (phi < 0) phi += 2 * Math.PI; // Test hyperboloid intersection against clipping parameters if (phit.z < zmin || phit.z > zmax || phi > phiMax) { if (thit == t1) return false; thit = t1; if (t1 > ray.maxt) return false; // Compute hyperboloid inverse mapping phit = ray.GetPointAt(thit); v = (phit.z - p1.z) / (p2.z - p1.z); pr = (1.0d - v) * p1 + v * p2; phi = Math.Atan2(pr.x * phit.y - phit.x * pr.y, phit.x * pr.x + phit.y * pr.y); if (phi < 0) phi += 2 * Math.PI; if (phit.z < zmin || phit.z > zmax || phi > phiMax) return false; } // Compute parametric representation of hyperboloid hit double u = phi / phiMax; // Compute hyperboloid $\dpdu$ and $\dpdv$ double cosphi = Math.Cos(phi), sinphi = Math.Sin(phi); Vector dpdu = new Vector(-phiMax * phit.y, phiMax * phit.x, 0.0d); Vector dpdv = new Vector((p2.x - p1.x) * cosphi - (p2.y - p1.y) * sinphi, (p2.x - p1.x) * sinphi + (p2.y - p1.y) * cosphi, p2.z - p1.z); // Compute hyperboloid $\dndu$ and $\dndv$ Vector d2Pduu = -phiMax * phiMax * new Vector(phit.x, phit.y, 0); Vector d2Pduv = phiMax * new Vector(-dpdv.y, dpdv.x, 0.0d); Vector d2Pdvv = new Vector(0, 0, 0); // Compute coefficients for fundamental forms double E = Geometry.Dot(dpdu, dpdu); double F = Geometry.Dot(dpdu, dpdv); double G = Geometry.Dot(dpdv, dpdv); Vector N = Geometry.Normalize(Geometry.Cross(dpdu, dpdv)); double e = Geometry.Dot(N, d2Pduu); double f = Geometry.Dot(N, d2Pduv); double g = Geometry.Dot(N, d2Pdvv); // Compute $\dndu$ and $\dndv$ from fundamental form coefficients double invEGF2 = 1.0d / (E * G - F * F); Normal dndu = new Normal((f * F - e * G) * invEGF2 * dpdu + (e * F - f * E) * invEGF2 * dpdv); Normal dndv = new Normal((g * F - f * G) * invEGF2 * dpdu + (f * F - g * E) * invEGF2 * dpdv); // Initialize _DifferentialGeometry_ from parametric information Transform o2w = ObjectToWorld; dg = new DifferentialGeometry(o2w.Apply(phit), o2w.Apply(dpdu), o2w.Apply(dpdv), o2w.Apply(dndu), o2w.Apply(dndv), u, v, this); // Update _tHit_ for quadric intersection tHit = thit; // Compute _rayEpsilon_ for quadric intersection rayEpsilon = 5e-4d * tHit; return true; }
public override bool IntersectP(Ray r) { double phi; Point phit; // Transform _Ray_ to object space Ray ray = WorldToObject.Apply(r); // Compute quadratic paraboloid coefficients double k = zmax / (radius * radius); double A = k * (ray.d.x * ray.d.x + ray.d.y * ray.d.y); double B = 2 * k * (ray.d.x * ray.o.x + ray.d.y * ray.o.y) - ray.d.z; double C = k * (ray.o.x * ray.o.x + ray.o.y * ray.o.y) - ray.o.z; // Solve quadratic equation for _t_ values double t0, t1; if (!Utility.Quadratic(A, B, C, out t0, out t1)) return false; // Compute intersection distance along ray if (t0 > ray.maxt || t1 < ray.mint) return false; double thit = t0; if (t0 < ray.mint) { thit = t1; if (thit > ray.maxt) return false; } // Compute paraboloid inverse mapping phit = ray.GetPointAt(thit); phi = Math.Atan2(phit.y, phit.x); if (phi < 0.0d) phi += 2.0d * Math.PI; // Test paraboloid intersection against clipping parameters if (phit.z < zmin || phit.z > zmax || phi > phiMax) { if (thit == t1) return false; thit = t1; if (t1 > ray.maxt) return false; // Compute paraboloid inverse mapping phit = ray.GetPointAt(thit); phi = Math.Atan2(phit.y, phit.x); if (phi < 0.0d) phi += 2.0d * Math.PI; if (phit.z < zmin || phit.z > zmax || phi > phiMax) return false; } return true; }
public RayDifferential(Point org, Vector dir, Ray parent, double start, double end = double.PositiveInfinity) : base(org, dir, start, end, parent.time, parent.depth + 1) { this.hasDifferentials = false; }
public Ray Apply(Ray r) { Ray ret = r.Copy(); ret.o = Apply(r.o); ret.d = Apply(r.d); return ret; }
public abstract bool Intersect(Ray r, out double tHit, out double rayEpsilon, out DifferentialGeometry dg);
public override bool Intersect(Ray r, out double tHit, out double rayEpsilon, out DifferentialGeometry dg) { double phi; Point phit; tHit = Double.NaN; rayEpsilon = Double.NaN; dg = null; // Transform _Ray_ to object space Ray ray = WorldToObject.Apply(r); // Compute quadratic sphere coefficients double A = ray.d.x * ray.d.x + ray.d.y * ray.d.y + ray.d.z * ray.d.z; double B = 2 * (ray.d.x * ray.o.x + ray.d.y * ray.o.y + ray.d.z * ray.o.z); double C = ray.o.x * ray.o.x + ray.o.y * ray.o.y + ray.o.z * ray.o.z - radius * radius; // Solve quadratic equation for _t_ values double t0, t1; if (!Utility.Quadratic(A, B, C, out t0, out t1)) return false; // Compute intersection distance along ray if (t0 > ray.maxt || t1 < ray.mint) return false; double thit = t0; if (t0 < ray.mint) { thit = t1; if (thit > ray.maxt) return false; } // Compute sphere hit position and $\phi$ phit = ray.GetPointAt(thit); if (phit.x == 0.0d && phit.y == 0.0d) phit.x = 1e-5d * radius; phi = Math.Atan2(phit.y, phit.x); if (phi < 0.0d) phi += 2.0d * Math.PI; // Test sphere intersection against clipping parameters if ((zmin > -radius && phit.z < zmin) || (zmax < radius && phit.z > zmax) || phi > phiMax) { if (thit == t1) return false; if (t1 > ray.maxt) return false; thit = t1; // Compute sphere hit position and $\phi$ phit = ray.GetPointAt(thit); if (phit.x == 0.0d && phit.y == 0.0d) phit.x = 1e-5d * radius; phi = Math.Atan2(phit.y, phit.x); if (phi < 0.0d) phi += 2.0d * Math.PI; if ((zmin > -radius && phit.z < zmin) || (zmax < radius && phit.z > zmax) || phi > phiMax) return false; } // Find parametric representation of sphere hit double u = phi / phiMax; double theta = Math.Acos(Utility.Clamp(phit.z / radius, -1.0d, 1.0d)); double v = (theta - thetaMin) / (thetaMax - thetaMin); // Compute sphere $\dpdu$ and $\dpdv$ double zradius = Math.Sqrt(phit.x * phit.x + phit.y * phit.y); double invzradius = 1.0d / zradius; double cosphi = phit.x * invzradius; double sinphi = phit.y * invzradius; Vector dpdu = new Vector(-phiMax * phit.y, phiMax * phit.x, 0); Vector dpdv = (thetaMax - thetaMin) * new Vector(phit.z * cosphi, phit.z * sinphi, -radius * Math.Sin(theta)); // Compute sphere $\dndu$ and $\dndv$ Vector d2Pduu = -phiMax * phiMax * new Vector(phit.x, phit.y, 0); Vector d2Pduv = (thetaMax - thetaMin) * phit.z * phiMax * new Vector(-sinphi, cosphi, 0.0d); Vector d2Pdvv = -(thetaMax - thetaMin) * (thetaMax - thetaMin) * new Vector(phit.x, phit.y, phit.z); // Compute coefficients for fundamental forms double E = Geometry.Dot(dpdu, dpdu); double F = Geometry.Dot(dpdu, dpdv); double G = Geometry.Dot(dpdv, dpdv); Vector N = Geometry.Normalize(Geometry.Cross(dpdu, dpdv)); double e = Geometry.Dot(N, d2Pduu); double f = Geometry.Dot(N, d2Pduv); double g = Geometry.Dot(N, d2Pdvv); // Compute $\dndu$ and $\dndv$ from fundamental form coefficients double invEGF2 = 1.0d / (E * G - F * F); Normal dndu = new Normal((f * F - e * G) * invEGF2 * dpdu + (e * F - f * E) * invEGF2 * dpdv); Normal dndv = new Normal((g * F - f * G) * invEGF2 * dpdu + (f * F - g * E) * invEGF2 * dpdv); // Initialize _DifferentialGeometry_ from parametric information Transform o2w = ObjectToWorld; dg = new DifferentialGeometry(o2w.Apply(phit), o2w.Apply(dpdu), o2w.Apply(dpdv), o2w.Apply(dndu), o2w.Apply(dndv), u, v, this); // Update _tHit_ for quadric intersection tHit = thit; // Compute _rayEpsilon_ for quadric intersection rayEpsilon = 5e-4d * tHit; 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; }
public override bool IntersectP(Ray r) { double phi; Point phit; // Transform _Ray_ to object space Ray ray = WorldToObject.Apply(r); // Compute quadratic sphere coefficients double A = ray.d.x * ray.d.x + ray.d.y * ray.d.y + ray.d.z * ray.d.z; double B = 2 * (ray.d.x * ray.o.x + ray.d.y * ray.o.y + ray.d.z * ray.o.z); double C = ray.o.x * ray.o.x + ray.o.y * ray.o.y + ray.o.z * ray.o.z - radius * radius; // Solve quadratic equation for _t_ values double t0, t1; if (!Utility.Quadratic(A, B, C, out t0, out t1)) return false; // Compute intersection distance along ray if (t0 > ray.maxt || t1 < ray.mint) return false; double thit = t0; if (t0 < ray.mint) { thit = t1; if (thit > ray.maxt) return false; } // Compute sphere hit position and $\phi$ phit = ray.GetPointAt(thit); if (phit.x == 0.0d && phit.y == 0.0d) phit.x = 1e-5d * radius; phi = Math.Atan2(phit.y, phit.x); if (phi < 0.0d) phi += 2.0d * Math.PI; // Test sphere intersection against clipping parameters if ((zmin > -radius && phit.z < zmin) || (zmax < radius && phit.z > zmax) || phi > phiMax) { if (thit == t1) return false; if (t1 > ray.maxt) return false; thit = t1; // Compute sphere hit position and $\phi$ phit = ray.GetPointAt(thit); if (phit.x == 0.0d && phit.y == 0.0d) phit.x = 1e-5d * radius; phi = Math.Atan2(phit.y, phit.x); if (phi < 0.0d) phi += 2.0d * Math.PI; if ((zmin > -radius && phit.z < zmin) || (zmax < radius && phit.z > zmax) || phi > phiMax) return false; } return true; }
public override bool IntersectP(Ray r) { return shape.IntersectP(r); }
public override bool IntersectP(Ray r) { throw new NotImplementedException(); }
public abstract bool Intersect(Ray r, Intersection isect);
public override bool Intersect(Ray r, out double tHit, out double rayEpsilon, out DifferentialGeometry dg) { double phi; Point phit; tHit = Double.NaN; rayEpsilon = Double.NaN; dg = null; // Transform _Ray_ to object space Ray ray = WorldToObject.Apply(r); // Compute quadratic paraboloid coefficients double k = zmax / (radius * radius); double A = k * (ray.d.x * ray.d.x + ray.d.y * ray.d.y); double B = 2 * k * (ray.d.x * ray.o.x + ray.d.y * ray.o.y) - ray.d.z; double C = k * (ray.o.x * ray.o.x + ray.o.y * ray.o.y) - ray.o.z; // Solve quadratic equation for _t_ values double t0, t1; if (!Utility.Quadratic(A, B, C, out t0, out t1)) return false; // Compute intersection distance along ray if (t0 > ray.maxt || t1 < ray.mint) return false; double thit = t0; if (t0 < ray.mint) { thit = t1; if (thit > ray.maxt) return false; } // Compute paraboloid inverse mapping phit = ray.GetPointAt(thit); phi = Math.Atan2(phit.y, phit.x); if (phi < 0.0d) phi += 2.0d * Math.PI; // Test paraboloid intersection against clipping parameters if (phit.z < zmin || phit.z > zmax || phi > phiMax) { if (thit == t1) return false; thit = t1; if (t1 > ray.maxt) return false; // Compute paraboloid inverse mapping phit = ray.GetPointAt(thit); phi = Math.Atan2(phit.y, phit.x); if (phi < 0.0d) phi += 2.0d * Math.PI; if (phit.z < zmin || phit.z > zmax || phi > phiMax) return false; } // Find parametric representation of paraboloid hit double u = phi / phiMax; double v = (phit.z - zmin) / (zmax - zmin); // Compute parabaloid $\dpdu$ and $\dpdv$ Vector dpdu = new Vector(-phiMax * phit.y, phiMax * phit.x, 0.0d); Vector dpdv = (zmax - zmin) * new Vector(phit.x / (2.0d * phit.z), phit.y / (2.0d * phit.z), 1.0d); // Compute parabaloid $\dndu$ and $\dndv$ Vector d2Pduu = -phiMax * phiMax * new Vector(phit.x, phit.y, 0); Vector d2Pduv = (zmax - zmin) * phiMax * new Vector(-phit.y / (2.0d * phit.z), phit.x / (2.0d * phit.z), 0); Vector d2Pdvv = -(zmax - zmin) * (zmax - zmin) * new Vector(phit.x / (4.0d * phit.z * phit.z), phit.y / (4.0d * phit.z * phit.z), 0.0d); // Compute coefficients for fundamental forms double E = Geometry.Dot(dpdu, dpdu); double F = Geometry.Dot(dpdu, dpdv); double G = Geometry.Dot(dpdv, dpdv); Vector N = Geometry.Normalize(Geometry.Cross(dpdu, dpdv)); double e = Geometry.Dot(N, d2Pduu); double f = Geometry.Dot(N, d2Pduv); double g = Geometry.Dot(N, d2Pdvv); // Compute $\dndu$ and $\dndv$ from fundamental form coefficients double invEGF2 = 1.0d / (E * G - F * F); Normal dndu = new Normal((f * F - e * G) * invEGF2 * dpdu + (e * F - f * E) * invEGF2 * dpdv); Normal dndv = new Normal((g * F - f * G) * invEGF2 * dpdu + (f * F - g * E) * invEGF2 * dpdv); // Initialize _DifferentialGeometry_ from parametric information Transform o2w = ObjectToWorld; dg = new DifferentialGeometry(o2w.Apply(phit), o2w.Apply(dpdu), o2w.Apply(dpdv), o2w.Apply(dndu), o2w.Apply(dndv), u, v, this); // Update _tHit_ for quadric intersection tHit = thit; // Compute _rayEpsilon_ for quadric intersection rayEpsilon = 5e-4d * tHit; return true; }
public override bool IntersectP(Ray r) { double phi, v; Point phit; // Transform _Ray_ to object space Ray ray = WorldToObject.Apply(r); // Compute quadratic hyperboloid coefficients double A = a * ray.d.x * ray.d.x + a * ray.d.y * ray.d.y - c * ray.d.z * ray.d.z; double B = 2.0d * (a * ray.d.x * ray.o.x + a * ray.d.y * ray.o.y - c * ray.d.z * ray.o.z); double C = a * ray.o.x * ray.o.x + a * ray.o.y * ray.o.y - c * ray.o.z * ray.o.z - 1; // Solve quadratic equation for _t_ values double t0, t1; if (!Utility.Quadratic(A, B, C, out t0, out t1)) return false; // Compute intersection distance along ray if (t0 > ray.maxt || t1 < ray.mint) return false; double thit = t0; if (t0 < ray.mint) { thit = t1; if (thit > ray.maxt) return false; } // Compute hyperboloid inverse mapping phit = ray.GetPointAt(thit); v = (phit.z - p1.z) / (p2.z - p1.z); Point pr = (1.0d - v) * p1 + v * p2; phi = Math.Atan2(pr.x * phit.y - phit.x * pr.y, phit.x * pr.x + phit.y * pr.y); if (phi < 0) phi += 2 * Math.PI; // Test hyperboloid intersection against clipping parameters if (phit.z < zmin || phit.z > zmax || phi > phiMax) { if (thit == t1) return false; thit = t1; if (t1 > ray.maxt) return false; // Compute hyperboloid inverse mapping phit = ray.GetPointAt(thit); v = (phit.z - p1.z) / (p2.z - p1.z); pr = (1.0d - v) * p1 + v * p2; phi = Math.Atan2(pr.x * phit.y - phit.x * pr.y, phit.x * pr.x + phit.y * pr.y); if (phi < 0) phi += 2 * Math.PI; if (phit.z < zmin || phit.z > zmax || phi > phiMax) return false; } return true; }
public RayDifferential(Ray ray) : base(ray.o, ray.d, ray.mint, ray.maxt, ray.time, ray.depth) { this.hasDifferentials = false; }
public override bool Intersect(Ray r, out double tHit, out double rayEpsilon, out DifferentialGeometry dg) { throw new NotImplementedException(); }