Example #1
0
        /// <inheritdoc />
        public override double GenerateRay(CameraSample sample, out Ray ray)
        {
            //ProfilePhase prof(Prof::GenerateCameraRay);
            // Compute raster and camera sample positions
            Point3D pFilm   = new Point3D(sample.FilmPoint.X, sample.FilmPoint.Y, 0.0);
            Point3D pCamera = RasterToCamera.AtPoint(pFilm);

            ray = new Ray(new Point3D(0.0, 0.0, 0.0), pCamera.ToVector3D().Normalize());
            // Modify ray for depth of field
            if (LensRadius > 0.0)
            {
                // Sample point on lens
                Point2D pLens = LensRadius * Sampling.ConcentricSampleDisk(sample.LensPoint);

                // Compute point on plane of focus
                double  ft     = FocalDistance / ray.Direction.Z;
                Point3D pFocus = ray.AtPoint(ft);

                // Update ray for effect of lens
                ray.Origin    = new Point3D(pLens.X, pLens.Y, 0.0);
                ray.Direction = (pFocus - ray.Origin).ToVector3D().Normalize();
            }
            ray.Time   = PbrtMath.Lerp(sample.Time, ShutterOpen, ShutterClose);
            ray.Medium = Medium;
            ray        = CameraToWorld.ExecuteTransform(ray);
            return(1.0);
        }
Example #2
0
        public Point3D ExecuteTransform(Point3D p, out Vector3D pError)
        {
            double x = p.X, y = p.Y, z = p.Z;
            // Compute transformed coordinates from point _pt_
            double xp = M[0, 0] * x + M[0, 1] * y + M[0, 2] * z + M[0, 3];
            double yp = M[1, 0] * x + M[1, 1] * y + M[1, 2] * z + M[1, 3];
            double zp = M[2, 0] * x + M[2, 1] * y + M[2, 2] * z + M[2, 3];
            double wp = M[3, 0] * x + M[3, 1] * y + M[3, 2] * z + M[3, 3];

            // Compute absolute error for transformed point
            double xAbsSum = (Math.Abs(M[0, 0] * x) + Math.Abs(M[0, 1] * y) +
                              Math.Abs(M[0, 2] * z) + Math.Abs(M[0, 3]));
            double yAbsSum = (Math.Abs(M[1, 0] * x) + Math.Abs(M[1, 1] * y) +
                              Math.Abs(M[1, 2] * z) + Math.Abs(M[1, 3]));
            double zAbsSum = (Math.Abs(M[2, 0] * x) + Math.Abs(M[2, 1] * y) +
                              Math.Abs(M[2, 2] * z) + Math.Abs(M[2, 3]));

            pError = PbrtMath.Gamma(3) * new Vector3D(xAbsSum, yAbsSum, zAbsSum);
            //CHECK_NE(wp, 0);
            if (wp == 1.0)
            {
                return(new Point3D(xp, yp, zp));
            }
            else
            {
                return(new Point3D(xp, yp, zp) / wp);
            }
        }
Example #3
0
        public bool IntersectP(Ray ray, out double hitt0, out double hitt1)
        {
            double t0 = 0, t1 = ray.TMax;

            for (int i = 0; i < 3; ++i)
            {
                // Update interval for _i_th bounding box slab
                double invRayDir = 1 / ray.Direction[i];
                double tNear     = (MinPoint[i] - ray.Origin[i]) * invRayDir;
                double tFar      = (MaxPoint[i] - ray.Origin[i]) * invRayDir;

                // Update parametric interval from slab intersection $t$ values
                if (tNear > tFar)
                {
                    double temp = tNear;
                    tNear = tFar;
                    tFar  = temp;
                }

                // Update _tFar_ to ensure robust ray--bounds intersection
                tFar *= 1 + 2 * PbrtMath.Gamma(3);
                t0    = tNear > t0 ? tNear : t0;
                t1    = tFar < t1 ? tFar : t1;
                if (t0 > t1)
                {
                    hitt0 = 0.0;
                    hitt1 = 0.0;
                    return(false);
                }
            }
            hitt0 = t0;
            hitt1 = t1;
            return(true);
        }
Example #4
0
        public Point3D OffsetRayOrigin(Vector3D pError, Normal3D n, Vector3D w)
        {
            double d = n.Abs().Dot(pError);

            // We have tons of precision; for now bump up the offset a bunch just
            // to be extra sure that we start on the right side of the surface
            // (In case of any bugs in the epsilons code...)
            d *= 1024.0;

            Point3D offset = d * n.ToPoint3D();

            if (w.Dot(n) < 0.0)
            {
                offset = -offset;
            }

            Point3D po = this + offset;

            // Round offset point _po_ away from _p_
            for (int i = 0; i < 3; ++i)
            {
                if (offset[i] > 0.0)
                {
                    po[i] = PbrtMath.NextFloatUp(po[i]);
                }
                else if (offset[i] < 0.0)
                {
                    po[i] = PbrtMath.NextFloatDown(po[i]);
                }
            }

            return(po);
        }
Example #5
0
        /// <inheritdoc />
        public override double GenerateRayDifferential(CameraSample sample, out RayDifferential ray)
        {
            //ProfilePhase prof(Prof::GenerateCameraRay);
            // Compute raster and camera sample positions
            Point3D  pFilm   = new Point3D(sample.FilmPoint.X, sample.FilmPoint.Y, 0.0);
            Point3D  pCamera = RasterToCamera.ExecuteTransform(pFilm);
            Vector3D dir     = new Vector3D(pCamera.X, pCamera.Y, pCamera.Z).Normalize();

            ray = new RayDifferential(new Point3D(0.0, 0.0, 0.0), dir);
            // Modify ray for depth of field
            if (LensRadius > 0.0)
            {
                // Sample point on lens
                Point2D pLens = LensRadius * Sampling.ConcentricSampleDisk(sample.LensPoint);

                // Compute point on plane of focus
                double  ft     = FocalDistance / ray.Direction.Z;
                Point3D pFocus = ray.AtPoint(ft);

                // Update ray for effect of lens
                ray.Origin    = new Point3D(pLens.X, pLens.Y, 0.0);
                ray.Direction = (pFocus - ray.Origin).ToVector3D().Normalize();
            }

            // Compute offset rays for _PerspectiveCamera_ ray differentials
            if (LensRadius > 0.0)
            {
                // Compute _PerspectiveCamera_ ray differentials accounting for lens

                // Sample point on lens
                Point2D  pLens  = LensRadius * Sampling.ConcentricSampleDisk(sample.LensPoint);
                Vector3D dx     = (pCamera.ToVector3D() + _dxCamera).Normalize();
                double   ft     = FocalDistance / dx.Z;
                Point3D  pFocus = new Point3D(0.0, 0.0, 0.0) + (ft * dx).ToPoint3D();
                ray.RxOrigin    = new Point3D(pLens.X, pLens.Y, 0.0);
                ray.RxDirection = (pFocus - ray.RxOrigin).ToVector3D().Normalize();

                Vector3D dy = (pCamera.ToVector3D() + _dyCamera).Normalize();
                ft              = FocalDistance / dy.Z;
                pFocus          = new Point3D(0.0, 0.0, 0.0) + (ft * dy).ToPoint3D();
                ray.RyOrigin    = new Point3D(pLens.X, pLens.Y, 0.0);
                ray.RyDirection = (pFocus - ray.RyOrigin).ToVector3D().Normalize();
            }
            else
            {
                ray.RxOrigin    = ray.RyOrigin = ray.Origin;
                ray.RxDirection = (pCamera.ToVector3D() + _dxCamera).Normalize();
                ray.RyDirection = (pCamera.ToVector3D() + _dyCamera).Normalize();
            }
            ray.Time   = PbrtMath.Lerp(sample.Time, ShutterOpen, ShutterClose);
            ray.Medium = Medium;
            ray        = new RayDifferential(CameraToWorld.ExecuteTransform(ray))
            {
                HasDifferentials = true
            };
            return(1.0);
        }
Example #6
0
        public static Transform Perspective(double fov, float n, double f)
        {
            // Perform projective divide for perspective projection
            Matrix4x4 persp = new Matrix4x4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, f / (f - n), -f * n / (f - n),
                                            0, 0, 1, 0);

            // Scale canonical perspective view to specified field of view
            double invTanAng = 1.0 / Math.Tan(PbrtMath.Radians(fov) / 2);

            return(Transform.Scale(invTanAng, invTanAng, 1.0) * new Transform(persp));
        }
Example #7
0
        public static Camera Create(ParamSet paramSet, AnimatedTransform cam2World, Film film, Medium medium)
        {
            // Extract common camera parameters from _ParamSet_
            double shutteropen  = paramSet.FindOneFloat("shutteropen", 0.0);
            double shutterclose = paramSet.FindOneFloat("shutterclose", 1.0);

            if (shutterclose < shutteropen)
            {
                //Warning("Shutter close time [%f] < shutter open [%f].  Swapping them.",
                //        shutterclose, shutteropen);

                PbrtMath.Swap(ref shutterclose, ref shutteropen);
            }
            double lensradius    = paramSet.FindOneFloat("lensradius", 0.0);
            double focaldistance = paramSet.FindOneFloat("focaldistance", 1e6);
            double frame         = paramSet.FindOneFloat(
                "frameaspectratio",
                Convert.ToDouble(film.FullResolution.X) / Convert.ToDouble(film.FullResolution.Y));
            Bounds2D screen;

            if (frame > 1.0)
            {
                screen = new Bounds2D(new Point2D(-frame, -1.0), new Point2D(frame, 1.0));
            }
            else
            {
                screen = new Bounds2D(new Point2D(-1.0, -1.0 / frame), new Point2D(1.0, 1.0 / frame));
            }
            double[] sw = paramSet.FindFloat("screenwindow");
            if (sw != null)
            {
                if (sw.Length == 4)
                {
                    screen = new Bounds2D(new Point2D(sw[0], sw[2]), new Point2D(sw[1], sw[3]));
                }
                else
                {
                    //Error("\"screenwindow\" should have four values");
                }
            }
            double fov     = paramSet.FindOneFloat("fov", 90.0);
            double halffov = paramSet.FindOneFloat("halffov", -1.0);

            if (halffov > 0.0)
            {
                // hack for structure synth, which exports half of the full fov
                fov = 2.0 * halffov;
            }

            return(new PerspectiveCamera(cam2World, screen, shutteropen, shutterclose,
                                         lensradius, focaldistance, fov, film, medium));
        }
Example #8
0
        public bool IntersectP(Ray ray, Vector3D invDir, bool[] dirIsNeg)
        {
            // Check for ray intersection against $x$ and $y$ slabs
            double tMin  = (this[dirIsNeg[0] ? 1 : 0].X - ray.Origin.X) * invDir.X;
            double tMax  = (this[dirIsNeg[0] ? 0 : 1].X - ray.Origin.X) * invDir.X;
            double tyMin = (this[dirIsNeg[1] ? 1 : 0].Y - ray.Origin.Y) * invDir.Y;
            double tyMax = (this[dirIsNeg[1] ? 0 : 1].Y - ray.Origin.Y) * invDir.Y;

            // Update _tMax_ and _tyMax_ to ensure robust bounds intersection
            tMax  *= 1.0 + 2.0 * PbrtMath.Gamma(3);
            tyMax *= 1.0 + 2.0 * PbrtMath.Gamma(3);
            if (tMin > tyMax || tyMin > tMax)
            {
                return(false);
            }

            if (tyMin > tMin)
            {
                tMin = tyMin;
            }

            if (tyMax < tMax)
            {
                tMax = tyMax;
            }

            // Check for ray intersection against $z$ slab
            double tzMin = (this[dirIsNeg[2] ? 1 : 0].Z - ray.Origin.Z) * invDir.Z;
            double tzMax = (this[dirIsNeg[2] ? 0 : 1].Z - ray.Origin.Z) * invDir.Z;

            // Update _tzMax_ to ensure robust bounds intersection
            tzMax *= 1.0 + 2.0 * PbrtMath.Gamma(3);
            if (tMin > tzMax || tzMin > tMax)
            {
                return(false);
            }

            if (tzMin > tMin)
            {
                tMin = tzMin;
            }

            if (tzMax < tMax)
            {
                tMax = tzMax;
            }

            return((tMin < ray.TMax) && (tMax > 0.0));
        }
Example #9
0
        // Returns the solid angle subtended by the shape w.r.t. the reference
        // point p, given in world space. Some shapes compute this value in
        // closed-form, while the default implementation uses Monte Carlo
        // integration; the nSamples parameter determines how many samples are
        // used in this case.
        public virtual double SolidAngle(Point3D p, int nSamples = 512)
        {
            Interaction it = new Interaction(p, new Normal3D(), new Vector3D(), new Vector3D(0.0, 0.0, 1.0), 0.0,
                                             new MediumInterface());

            double solidAngle = 0.0;

            for (int i = 0; i < nSamples; ++i)
            {
                Point2D     u = new Point2D(PbrtMath.RadicalInverse(0, i), PbrtMath.RadicalInverse(1, i));
                double      pdf;
                Interaction pShape = Sample(it, u, out pdf);
                if (pdf > 0.0 && !IntersectP(new Ray(p, (pShape.P - p).ToVector3D(), 0.999)))
                {
                    solidAngle += 1.0 / pdf;
                }
            }
            return(solidAngle / nSamples);
        }
Example #10
0
 public Point2I Lerp(Point2I t)
 {
     return(new Point2I(PbrtMath.Lerp(t.X, MinPoint.X, MaxPoint.X),
                        PbrtMath.Lerp(t.Y, MinPoint.Y, MaxPoint.Y)));
 }
Example #11
0
 public Point3D Lerp(Point3D t)
 {
     return(new Point3D(PbrtMath.Lerp(t.X, MinPoint.X, MaxPoint.X),
                        PbrtMath.Lerp(t.Y, MinPoint.Y, MaxPoint.Y),
                        PbrtMath.Lerp(t.Z, MinPoint.Z, MaxPoint.Z)));
 }
Example #12
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;
                    }
Example #13
0
        public static Film Create(PbrtOptions options, ParamSet paramSet, Filter filter)
        {
            string filename;

            if (options.ImageFile != "")
            {
                filename = options.ImageFile;
                string paramsFilename = paramSet.FindOneString("filename", "");
                if (paramsFilename != "")
                {
                    //Warning(
                    //  "Output filename supplied on command line, \"%s\" is overriding filename provided in scene description file, \"%s\".",
                    //PbrtOptions.imageFile.c_str(), paramsFilename.c_str());
                }
            }
            else
            {
                filename = paramSet.FindOneString("filename", "pbrt.exr");
            }

            int xres = paramSet.FindOneInt("xresolution", 1280);
            int yres = paramSet.FindOneInt("yresolution", 720);

            if (options.QuickRender)
            {
                xres = Math.Max(1, xres / 4);
            }

            if (options.QuickRender)
            {
                yres = Math.Max(1, yres / 4);
            }

            Bounds2D crop;
            int      cwi;

            double[] cr = paramSet.FindFloat("cropwindow");
            if (cr != null && cr.Length == 4)
            {
                double minx = PbrtMath.Clamp(Math.Min(cr[0], cr[1]), 0.0, 1.0);
                double maxx = PbrtMath.Clamp(Math.Max(cr[0], cr[1]), 0.0, 1.0);
                double miny = PbrtMath.Clamp(Math.Min(cr[2], cr[3]), 0.0, 1.0);
                double maxy = PbrtMath.Clamp(Math.Max(cr[2], cr[3]), 0.0, 1.0);
                crop = new Bounds2D(new Point2D(minx, miny), new Point2D(maxx, maxy));
            }
            else if (cr != null)
            {
                throw new InvalidOperationException();
                //Error("%d values supplied for \"cropwindow\". Expected 4.", cwi);
            }
            else
            {
                crop = new Bounds2D(new Point2D(PbrtMath.Clamp(options.CropWindow[0, 0], 0.0, 1.0),
                                                PbrtMath.Clamp(options.CropWindow[1, 0], 0.0, 1.0)),
                                    new Point2D(PbrtMath.Clamp(options.CropWindow[0, 1], 0.0, 1.0),
                                                PbrtMath.Clamp(options.CropWindow[1, 1], 0.0, 1.0)));
            }

            double scale              = paramSet.FindOneFloat("scale", 1.0);
            double diagonal           = paramSet.FindOneFloat("diagonal", 35.0);
            double maxSampleLuminance = paramSet.FindOneFloat("maxsampleluminance",
                                                              double.PositiveInfinity);

            return(new Film(new Point2I(xres, yres), crop, filter, diagonal,
                            filename, scale, maxSampleLuminance));
        }
Example #14
0
        public Matrix4x4 Inverse()
        {
            int[] indxc = new int[4];
            int[] indxr = new int[4];
            int[] ipiv  =
            {
                0,
                0,
                0,
                0
            };
            double[,] minv = new double[4, 4];

            Array.Copy(_m, minv, 4 * 4);
            for (int i = 0; i < 4; i++)
            {
                int    irow = 0;
                int    icol = 0;
                double big  = 0.0;
                // Choose pivot
                for (int j = 0; j < 4; j++)
                {
                    if (ipiv[j] != 1)
                    {
                        for (int k = 0; k < 4; k++)
                        {
                            if (ipiv[k] == 0)
                            {
                                if (Math.Abs(minv[j, k]) >= big)
                                {
                                    big  = Math.Abs(minv[j, k]);
                                    irow = j;
                                    icol = k;
                                }
                            }
                            else if (ipiv[k] > 1.0)
                            {
                                throw new InvalidOperationException("Singular matrix in MatrixInvert");
                            }
                        }
                    }
                }

                ++ipiv[icol];
                // Swap rows _irow_ and _icol_ for pivot
                if (irow != icol)
                {
                    for (int k = 0; k < 4; ++k)
                    {
                        PbrtMath.Swap(ref minv[irow, k], ref minv[icol, k]);
                    }
                }

                indxr[i] = irow;
                indxc[i] = icol;
                if (minv[icol, icol] == 0.0)
                {
                    throw new InvalidOperationException("Singular matrix in MatrixInvert");
                }

                // Set $m[icol,icol]$ to one by scaling row _icol_ appropriately
                double pivinv = 1.0 / minv[icol, icol];
                minv[icol, icol] = 1.0;
                for (int j = 0; j < 4; j++)
                {
                    minv[icol, j] *= pivinv;
                }

                // Subtract this row from others to zero out their columns
                for (int j = 0; j < 4; j++)
                {
                    if (j != icol)
                    {
                        double save = minv[j, icol];
                        minv[j, icol] = 0;
                        for (int k = 0; k < 4; k++)
                        {
                            minv[j, k] -= minv[icol, k] * save;
                        }
                    }
                }
            }

            // Swap columns to reflect permutation
            for (int j = 3; j >= 0; j--)
            {
                if (indxr[j] != indxc[j])
                {
                    for (int k = 0; k < 4; k++)
                    {
                        PbrtMath.Swap(ref minv[k, indxr[j]], ref minv[k, indxc[j]]);
                    }
                }
            }

            return(new Matrix4x4(minv));
        }