コード例 #1
0
        public override (SurfaceInteraction, double) Sample(SurfaceInteraction _si)
        {
            SurfaceInteraction si  = WorldToObject.Apply(_si);
            double             dc2 = si.Point.LengthSquared();

            if (dc2 <= Radius * Radius)
            {
                // Point inside sphere
                return(base.Sample(_si));
            }

            // Point outside sphere
            double dc = Math.Sqrt(dc2);

            double sinThetaMax = Radius / dc;
            double cosThetaMax = Utils.SinToCos(sinThetaMax);

            // Determine theta and phi for uniform cone sampling
            double cosTheta = (cosThetaMax - 1) * Samplers.ThreadSafeRandom.NextDouble() + 1;
            double sinTheta = Utils.CosToSin(cosTheta);
            double phi      = Samplers.ThreadSafeRandom.NextDouble() * 2.0 * Math.PI;

            // Distance between reference point and sample point on sphere
            double ds = dc * cosTheta - Math.Sqrt(Math.Max(0, Radius * Radius - dc2 * sinTheta * sinTheta));

            // Kosinusni zakon
            double cosAlpha = (dc2 + Radius * Radius - ds * ds) / (2 * dc * Radius);
            double sinAlpha = Utils.CosToSin(cosAlpha);

            // Construct coordinate system and use phi and theta as spherical coordinates to get point on sphere
            Vector3 wcZ = si.Point.Clone().Normalize();

            (Vector3 wcX, Vector3 wcY) = Utils.CoordinateSystem(wcZ);

            Vector3 nObj = Utils.SphericalDirection(sinAlpha, cosAlpha, phi, wcX, wcY, wcZ);
            Vector3 pObj = nObj * Radius;

            // Surface interaction
            Vector3            dpdu     = new Vector3(-nObj.y, nObj.x, 0.0);
            SurfaceInteraction siSample = new SurfaceInteraction(pObj, nObj, Vector3.ZeroVector, dpdu, this);

            // Uniform cone PDF
            double pdf = Samplers.UniformConePdf(cosThetaMax);

            return(ObjectToWorld.Apply(siSample), pdf);
        }