public static Vector UniformSampleCone(double u1, double u2, double costhetamax, Vector x, Vector y, Vector z)
 {
     double costheta = Utility.Lerp(u1, costhetamax, 1.0d);
     double sintheta = Math.Sqrt(1.0d - costheta * costheta);
     double phi = u2 * 2.0d * Math.PI;
     return Math.Cos(phi) * sintheta * x + Math.Sin(phi) * sintheta * y + costheta * z;
 }
 public void ScaleDifferentials(double s)
 {
     this.rxOrigin = o + (rxOrigin - o) * s;
     this.ryOrigin = o + (ryOrigin - o) * s;
     this.rxDirection = d + (rxDirection - d) * s;
     this.ryDirection = d + (ryDirection - d) * s;
 }
 public static Vector Cross(Normal v1, Vector v2)
 {
     if (v1.HasNaNs() || v2.HasNaNs()) throw new InvalidOperationException();
     double v1x = v1.x, v1y = v1.y, v1z = v1.z;
     double v2x = v2.x, v2y = v2.y, v2z = v2.z;
     return new Vector((v1y * v2z) - (v1z * v2y),
                   (v1z * v2x) - (v1x * v2z),
                   (v1x * v2y) - (v1y * v2x));
 }
 public Ray(Point origin, Vector direction, double start, double end = double.PositiveInfinity, double t = 0.0d, int d = 0)
 {
     this.o = origin;
     this.d = direction;
     this.mint = start;
     this.maxt = end;
     this.time = t;
     this.depth = d;
 }
 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 DifferentialGeometry(Point P, Vector DPDU, Vector DPDV, Normal DNDU, Normal DNDV, double uu, double vv, Shape sh)
        {
            p = P; dpdu = DPDU; dpdv = DPDV; dndu = DNDU; dndv = DNDV;
            // Initialize _DifferentialGeometry_ from parameters
            nn = new Normal(Geometry.Normalize(Geometry.Cross(dpdu, dpdv)));
            u = uu;
            v = vv;
            shape = sh;
            dudx = dvdx = dudy = dvdy = 0.0d;

            // Adjust normal based on orientation and handedness
            if (shape != null && (shape.ReverseOrientation ^ shape.TransformSwapsHandedness)) nn *= -1.0d;
        }
 public static void CoordinateSystem(Vector v1, out Vector v2, out Vector v3)
 {
     if (Math.Abs(v1.x) > Math.Abs(v1.y))
     {
         double invLen = 1.0d / Math.Sqrt(v1.x * v1.x + v1.z * v1.z);
         v2 = new Vector(-v1.z * invLen, 0.0d, v1.x * invLen);
     }
     else
     {
         double invLen = 1.0d / Math.Sqrt(v1.y * v1.y + v1.z * v1.z);
         v2 = new Vector(0.0d, v1.z * invLen, -v1.y * invLen);
     }
     v3 = Cross(v1, v2);
 }
        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 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 TriangleMesh(Transform o2w, Transform w2o, bool ro, int nt, int nv, int[] vi, Point[] P, Normal[] N, Vector[] S, double[] uv, Texture<double> atex)
     : base(o2w, w2o, ro)
 {
     alphaTexture = atex;
     ntris = nt;
     nverts = nv;
     vertexIndex = new int[ntris * 3];
     Array.Copy(vi, 0, vertexIndex, 0, ntris * 3);
     // Copy _uv_, _N_, and _S_ vertex data, if present
     if (uv != null)
     {
         uvs = new double[2 * nverts];
         Array.Copy(uv, 0, uvs, 0, 2 * nverts);
     }
     else
     {
         uvs = null;
     }
     p = new Point[nverts];
     if (N != null)
     {
         n = new Normal[nverts];
         Array.Copy(N, 0, n, 0, nverts);
     }
     else
     {
         n = null;
     }
     if (S != null)
     {
         s = new Vector[nverts];
         Array.Copy(S, 0, s, 0, nverts);
     }
     else
     {
         s = null;
     }
     // Transform mesh vertices to world space
     for (int i = 0; i < nverts; ++i)
     {
         p[i] = ObjectToWorld.Apply(P[i]);
     }
 }
        public void ComputeDifferentials(RayDifferential ray)
        {
            if (ray.hasDifferentials)
            {
                // Estimate screen space change in $\pt{}$ and $(u,v)$

                // Compute auxiliary intersection points with plane
                double d = -Geometry.Dot(nn, new Vector(p.x, p.y, p.z));
                Vector rxv = new Vector(ray.rxOrigin.x, ray.rxOrigin.y, ray.rxOrigin.z);
                double tx = -(Geometry.Dot(nn, rxv) + d) / Geometry.Dot(nn, ray.rxDirection);
                if (Double.IsNaN(tx))
                {
                    dudx = dvdx = 0.0d;
                    dudy = dvdy = 0.0d;
                    dpdx = dpdy = new Vector(0, 0, 0);
                    return;
                }
                Point px = ray.rxOrigin + tx * ray.rxDirection;
                Vector ryv = new Vector(ray.ryOrigin.x, ray.ryOrigin.y, ray.ryOrigin.z);
                double ty = -(Geometry.Dot(nn, ryv) + d) / Geometry.Dot(nn, ray.ryDirection);
                if (Double.IsNaN(ty))
                {
                    dudx = dvdx = 0.0d;
                    dudy = dvdy = 0.0d;
                    dpdx = dpdy = new Vector(0, 0, 0);
                    return;
                }
                Point py = ray.ryOrigin + ty * ray.ryDirection;
                dpdx = px - p;
                dpdy = py - p;

                // Compute $(u,v)$ offsets at auxiliary points

                // Initialize _A_, _Bx_, and _By_ matrices for offset computation
                double[,] A = new double[2, 2];
                double[] Bx = new double[2];
                double[] By = new double[2];

                int[] axes = new int[2];

                if (Math.Abs(nn.x) > Math.Abs(nn.y) && Math.Abs(nn.x) > Math.Abs(nn.z))
                {
                    axes[0] = 1; axes[1] = 2;
                }
                else if (Math.Abs(nn.y) > Math.Abs(nn.z))
                {
                    axes[0] = 0; axes[1] = 2;
                }
                else
                {
                    axes[0] = 0; axes[1] = 1;
                }

                // Initialize matrices for chosen projection plane
                A[0, 0] = dpdu[axes[0]];
                A[0, 1] = dpdv[axes[0]];
                A[1, 0] = dpdu[axes[1]];
                A[1, 1] = dpdv[axes[1]];
                Bx[0] = px[axes[0]] - p[axes[0]];
                Bx[1] = px[axes[1]] - p[axes[1]];
                By[0] = py[axes[0]] - p[axes[0]];
                By[1] = py[axes[1]] - p[axes[1]];

                if (!Utility.SolveLinearSystem2x2(A, Bx, out dudx, out dvdx))
                {
                    dudx = 0.0d; dvdx = 0.0d;
                }

                if (!Utility.SolveLinearSystem2x2(A, By, out dudy, out dvdy))
                {
                    dudy = 0.0d; dvdy = 0.0d;
                }
            }
            else
            {
                dudx = dvdx = 0.0d;
                dudy = dvdy = 0.0d;
                dpdx = dpdy = new Vector(0, 0, 0);
            }
        }
 public static double Dot(Normal n, Vector v)
 {
     if (n.HasNaNs() || v.HasNaNs()) throw new InvalidOperationException();
     return n.x * v.x + n.y * v.y + n.z * v.z;
 }
 public static double Dot(Vector v, Normal n)
 {
     if (v.HasNaNs() || n.HasNaNs()) throw new InvalidOperationException();
     return v.x * n.x + v.y * n.y + v.z * n.z;
 }
 public Normal(Vector v)
 {
     this.x = v.x;
     this.y = v.y;
     this.z = v.z;
 }
        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 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 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 Quaternion()
 {
     v = new Vector(0.0d, 0.0d, 0.0d); w = 1.0d;
 }
        public static Transform LookAt(Point pos, Point look, Vector up)
        {
            double[,] m = new double[4, 4];
            // Initialize fourth column of viewing matrix
            m[0, 3] = pos.x;
            m[1, 3] = pos.y;
            m[2, 3] = pos.z;
            m[3, 3] = 1;

            // Initialize first three columns of viewing matrix
            Vector dir = Geometry.Normalize(look - pos);
            Vector left = Geometry.Normalize(Geometry.Cross(Geometry.Normalize(up), dir));
            Vector newUp = Geometry.Cross(dir, left);
            m[0, 0] = left.x;
            m[1, 0] = left.y;
            m[2, 0] = left.z;
            m[3, 0] = 0.0d;
            m[0, 1] = newUp.x;
            m[1, 1] = newUp.y;
            m[2, 1] = newUp.z;
            m[3, 1] = 0.0d;
            m[0, 2] = dir.x;
            m[1, 2] = dir.y;
            m[2, 2] = dir.z;
            m[3, 2] = 0.0d;
            Matrix4x4 camToWorld = new Matrix4x4(m);
            return new Transform(Inverse(camToWorld), camToWorld);
        }
        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 double Pdf(Point p, Vector wi)
        {
            Point Pcenter = ObjectToWorld.Apply(new Point(0, 0, 0));
            // Return uniform weight if point inside sphere
            if (Geometry.DistanceSquared(p, Pcenter) - radius * radius < 1e-4d)
                return base.Pdf(p, wi);

            // Compute general sphere weight
            double sinThetaMax2 = radius * radius / Geometry.DistanceSquared(p, Pcenter);
            double cosThetaMax = Math.Sqrt(Math.Max(0.0d, 1.0d - sinThetaMax2));
            return MonteCarlo.UniformConePdf(cosThetaMax);
        }
 public void Expand(double delta)
 {
     pMin -= new Vector(delta, delta, delta);
     pMax += new Vector(delta, delta, delta);
 }
 public Spectrum Le(Vector w)
 {
     AreaLight area = primitive.GetAreaLight();
     return area != null ? area.L(dg.p, dg.nn, w) : new Spectrum(0.0d);
 }
 public Vector Apply(Vector v)
 {
     double x = v.x, y = v.y, z = v.z;
     return new Vector(m.m[0, 0] * x + m.m[0, 1] * y + m.m[0, 2] * z,
                   m.m[1, 0] * x + m.m[1, 1] * y + m.m[1, 2] * z,
                   m.m[2, 0] * x + m.m[2, 1] * y + m.m[2, 2] * z);
 }
 public RayDifferential(Point org, Vector dir, double start, double end = double.PositiveInfinity, double t = 0.0d, int d = 0)
     : base(org, dir, start, end, t, d)
 {
     this.hasDifferentials = false;
 }
 public void Apply(Vector v, ref Vector vt)
 {
     double x = v.x, y = v.y, z = v.z;
     vt.x = m.m[0, 0] * x + m.m[0, 1] * y + m.m[0, 2] * z;
     vt.y = m.m[1, 0] * x + m.m[1, 1] * y + m.m[1, 2] * z;
     vt.z = m.m[2, 0] * x + m.m[2, 1] * y + m.m[2, 2] * z;
 }
        public static Transform Rotate(double angle, Vector axis)
        {
            Vector a = Geometry.Normalize(axis);
            double s = Math.Sin(Utility.Radians(angle));
            double c = Math.Cos(Utility.Radians(angle));
            double[,] m = new double[4, 4];

            m[0, 0] = a.x * a.x + (1.0d - a.x * a.x) * c;
            m[0, 1] = a.x * a.y * (1.0d - c) - a.z * s;
            m[0, 2] = a.x * a.z * (1.0d - c) + a.y * s;
            m[0, 3] = 0;

            m[1, 0] = a.x * a.y * (1.0d - c) + a.z * s;
            m[1, 1] = a.y * a.y + (1.0d - a.y * a.y) * c;
            m[1, 2] = a.y * a.z * (1.0d - c) - a.x * s;
            m[1, 3] = 0;

            m[2, 0] = a.x * a.z * (1.0d - c) - a.y * s;
            m[2, 1] = a.y * a.z * (1.0d - c) + a.x * s;
            m[2, 2] = a.z * a.z + (1.0d - a.z * a.z) * c;
            m[2, 3] = 0;

            m[3, 0] = 0;
            m[3, 1] = 0;
            m[3, 2] = 0;
            m[3, 3] = 1;

            Matrix4x4 mat = new Matrix4x4(m);
            return new Transform(mat, Transpose(mat));
        }
 public Spectrum L(Point point, Normal normal, Vector w)
 {
     throw new NotImplementedException();
 }
 public Quaternion(Vector v, double w)
 {
     this.v = v;
     this.w = w;
 }
 public static Transform Translate(Vector delta)
 {
     Matrix4x4 m = new Matrix4x4(1, 0, 0, delta.x,
                 0, 1, 0, delta.y,
                 0, 0, 1, delta.z,
                 0, 0, 0, 1);
     Matrix4x4 minv = new Matrix4x4(1, 0, 0, -delta.x,
                    0, 1, 0, -delta.y,
                    0, 0, 1, -delta.z,
                    0, 0, 0, 1);
     return new Transform(m, minv);
 }