Example #1
0
        public void ComputeDifferentials(RayDifferential ray)
        {
            if (ray.HasDifferentials)
            {
                try
                {
                    // Estimate screen space change in $\pt{}$ and $(u,v)$

                    // Compute auxiliary intersection points with plane
                    double d  = N.Dot(P.ToVector3D());
                    double tx = -(N.Dot(ray.RxOrigin.ToVector3D()) - d) / N.Dot(ray.RxDirection);
                    if (double.IsInfinity(tx) || double.IsNaN(tx))
                    {
                        throw new InvalidOperationException();
                    }

                    Point3D px = (ray.RxOrigin.ToVector3D() + tx * ray.RxDirection).ToPoint3D();
                    double  ty = -(N.Dot(ray.RyOrigin.ToVector3D()) - d) / N.Dot(ray.RyDirection);
                    if (double.IsInfinity(ty) || double.IsNaN(ty))
                    {
                        throw new InvalidOperationException();
                    }

                    Point3D py = (ray.RyOrigin.ToVector3D() + ty * ray.RyDirection).ToPoint3D();
                    Dpdx = (px - P).ToVector3D();
                    Dpdy = (py - P).ToVector3D();

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

                    // Choose two dimensions to use for ray offset computation
                    int[] dim = new int[2];
                    if (Math.Abs(N.X) > Math.Abs(N.Y) && Math.Abs(N.X) > Math.Abs(N.Z))
                    {
                        dim[0] = 1;
                        dim[1] = 2;
                    }
                    else if (Math.Abs(N.Y) > Math.Abs(N.Z))
                    {
                        dim[0] = 0;
                        dim[1] = 2;
                    }
                    else
                    {
                        dim[0] = 0;
                        dim[1] = 1;
                    }

                    // Initialize _A_, _Bx_, and _By_ matrices for offset computation
                    double[,] a = new double[2, 2];
                    a[0, 0]     = Dpdu[dim[0]];
                    a[0, 1]     = Dpdv[dim[0]];
                    a[1, 0]     = Dpdu[dim[1]];
                    a[1, 1]     = Dpdv[dim[1]];

                    //Float A[2][2] = {{dpdu[dim[0]], dpdv[dim[0]]
                    //  },
                    //  {dpdu[dim[1]], dpdv[dim[1]]
                    //  }};
                    double[] bx = new double[2];
                    bx[0] = px[dim[0]] - P[dim[0]];
                    bx[1] = px[dim[1]] - P[dim[1]];

                    double[] by = new double[2];
                    by[0] = py[dim[0]] - P[dim[0]];
                    by[1] = py[dim[1]] - P[dim[1]];

                    if (PbrtMath.SolveLinearSystem2x2(a, bx, out double du1, out double dv1))
                    {
                        Dudx = du1;
                        Dvdx = dv1;
                    }
                    else
                    {
                        Dudx = 0.0;
                        Dvdx = 0.0;
                    }

                    if (PbrtMath.SolveLinearSystem2x2(a, by, out double du2, out double dv2))
                    {
                        Dudx = du2;
                        Dvdx = dv2;
                    }