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();
 }