コード例 #1
0
        public override (double?, SurfaceInteraction) Intersect(Ray r)
        {
            var ray = WorldToObject.Apply(r);

            // Compute plane intersection for quad

            // Reject intersections for rays parallel to the quad's plane
            if (ray.d.z == 0)
            {
                return(null, null);
            }

            double tShapeHit = -ray.o.z / ray.d.z;

            if (tShapeHit <= Renderer.Epsilon)
            {
                return(null, null);
            }

            // See if hit point is inside
            var pHit = ray.Point(tShapeHit);

            if (pHit.x < -width / 2 || pHit.x > width / 2 || pHit.y < -height / 2 || pHit.y > height / 2)
            {
                return(null, null);
            }

            // Refine disk intersection point
            pHit.z = 0;
            var dpdu = new Vector3(1, 0, 0);

            var si = new SurfaceInteraction(pHit, new Vector3(0, 0, 1), -ray.d, dpdu, this);

            return(tShapeHit, ObjectToWorld.Apply(si));
        }
コード例 #2
0
            public TransformBufferLayout(Matrix cameraToClipSpace, Matrix worldToCamera, Matrix objectToWorld)
            {
                Matrix clipSpaceToCamera = cameraToClipSpace;

                clipSpaceToCamera.Invert();
                Matrix cameraToWorld = worldToCamera;

                cameraToWorld.Invert();
                Matrix worldToObject = objectToWorld;

                worldToObject.Invert();

                CameraToClipSpace = cameraToClipSpace;
                ClipSpaceToCamera = clipSpaceToCamera;
                WorldToCamera     = worldToCamera;
                CameraToWorld     = cameraToWorld;
                WorldToClipSpace  = Matrix.Multiply(worldToCamera, cameraToClipSpace);
                ClipSpaceToWorld  = Matrix.Multiply(clipSpaceToCamera, cameraToWorld);
                ObjectToWorld     = objectToWorld;
                WorldToObject     = worldToObject;
                ObjectToCamera    = Matrix.Multiply(objectToWorld, worldToCamera);
                ObjectToClipSpace = Matrix.Multiply(ObjectToCamera, cameraToClipSpace);

                // transpose all as mem layout in hlsl constant buffer is row based
                CameraToClipSpace.Transpose();
                ClipSpaceToCamera.Transpose();
                WorldToCamera.Transpose();
                CameraToWorld.Transpose();
                WorldToClipSpace.Transpose();
                ClipSpaceToWorld.Transpose();
                ObjectToWorld.Transpose();
                WorldToObject.Transpose();
                ObjectToCamera.Transpose();
                ObjectToClipSpace.Transpose();
            }
コード例 #3
0
        public override (double?, SurfaceInteraction) Intersect(Ray _r)
        {
            Ray ray = WorldToObject.Apply(_r);

            double a = 1;
            double b = 2 * Vector3.Dot(ray.o, ray.d);
            double c = Vector3.Dot(ray.o, ray.o) - Radius * Radius;

            (bool hasSolution, double t0, double t1) = Utils.Quadratic(a, b, c);

            if (!hasSolution || (t0 < Renderer.Epsilon && t1 < Renderer.Epsilon))
            {
                return(null, null);
            }

            double tHit = (t0 < Renderer.Epsilon ? t1 : t0);

            Vector3 pHit   = ray.Point(tHit);
            Vector3 normal = pHit * (1.0 / Radius);
            Vector3 dpdu   = new Vector3(-pHit.y, pHit.x, 0);

            SurfaceInteraction si = new SurfaceInteraction(pHit, normal, -ray.d, dpdu, this);

            return(tHit, ObjectToWorld.Apply(si));
        }
コード例 #4
0
ファイル: Cylinder.cs プロジェクト: MassVOiD/aether
        private bool DoIntersection(Ray r, out float phi, out Point phit, out float thit)
        {
            phi = 0.0f;
            phit = new Point();
            thit = 0.0f;

            // Transform _Ray_ to object space
            Ray ray = WorldToObject.TransformRay(r);

            // Compute quadratic cylinder coefficients
            float A = ray.Direction.X * ray.Direction.X + ray.Direction.Y * ray.Direction.Y;
            float B = 2 * (ray.Direction.X * ray.Origin.X + ray.Direction.Y * ray.Origin.Y);
            float C = ray.Origin.X * ray.Origin.X + ray.Origin.Y * ray.Origin.Y - _radius * _radius;

            // Solve quadratic equation for _t_ values
            float t0, t1;
            if (!MathUtility.TryQuadratic(A, B, C, out t0, out t1))
                return false;

            // Compute intersection distance along ray
            if (t0 > ray.MaxT || t1 < ray.MinT)
                return false;
            thit = t0;
            if (t0 < ray.MinT)
            {
                thit = t1;
                if (thit > ray.MaxT)
                    return false;
            }

            // Compute cylinder hit point and $\phi$
            phit = ray.Evaluate(thit);
            phi = MathUtility.Atan2(phit.Y, phit.X);
            if (phi < 0.0)
                phi += 2.0f * MathUtility.Pi;

            // Test cylinder 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 cylinder hit point and $\phi$
                phit = ray.Evaluate(thit);
                phi = MathUtility.Atan2(phit.Y, phit.X);
                if (phi < 0.0f) phi += 2.0f * MathUtility.Pi;
                if (phit.Z < _zMin || phit.Z > _zMax || phi > _phiMax)
                    return false;
            }

            return true;
        }
コード例 #5
0
        public override double Pdf(SurfaceInteraction _si, Vector3 wi)
        {
            SurfaceInteraction si    = WorldToObject.Apply(_si);
            double             dist2 = si.Point.LengthSquared();

            if (dist2 <= Radius * Radius)
            {
                // Point inside sphere
                return(base.Pdf(_si, wi));
            }
            // Point outside sphere
            double sinThetaMax = Radius / Math.Sqrt(dist2);
            double cosThetaMax = Utils.SinToCos(sinThetaMax);

            return(Samplers.UniformConePdf(cosThetaMax));
        }
コード例 #6
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);
        }
コード例 #7
0
        public override (double?, SurfaceInteraction) Intersect(Ray r)
        {
            var ray = WorldToObject.Apply(r);

            // TODO: Compute quadratic sphere coefficients

            // TODO: Initialize _double_ ray coordinate values
            double a = (ray.d.x * ray.d.x) + (ray.d.y * ray.d.y) + (ray.d.z * ray.d.z);
            double b = ((ray.d.x * ray.o.x) + (ray.d.y * ray.o.y) + (ray.d.z * ray.o.z)) * 2;
            double c = (ray.o.x * ray.o.x) + (ray.o.y * ray.o.y) + (ray.o.z * ray.o.z) - (Radius * Radius);

            // TODO: Solve quadratic equation for _t_ values
            (bool ok, double t0, double t1) = Utils.Quadratic(a, b, c);
            // TODO: Check quadric shape _t0_ and _t1_ for nearest intersection
            if (!ok /*|| t0 > ray.max*/ || t1 <= 0)
            {
                return(null, null);
            }
            // TODO: Compute sphere hit position and $\phi$
            double tShapeHit = t0;

            if (tShapeHit <= Renderer.Epsilon)   // skor 0.
            {
                tShapeHit = t1;
                //if (t1 > ray.max)
                //{
                //    return (null, null);
                //}
            }

            Vector3 pHit = ray.Point(tShapeHit);

            //pHit.
            if (pHit.x == 0 && pHit.y == 0)
            {
                pHit.x = 1e-5 * Radius;
            }

            Vector3 dpdu = new Vector3(-pHit.y, pHit.x, 0);

            // TODO: Return shape hit and surface interaction

            return(tShapeHit, ObjectToWorld.Apply(new SurfaceInteraction(pHit, pHit, -ray.d, dpdu, this)));
        }
コード例 #8
0
ファイル: Disk.cs プロジェクト: MassVOiD/aether
        private bool DoIntersection(Ray r, out float phi, out float dist2, out Point phit, out float thit)
        {
            phi  = dist2 = thit = 0;
            phit = Point.Zero;

            // Transform _Ray_ to object space
            Ray ray = WorldToObject.TransformRay(r);

            // Compute plane intersection for disk
            if (Math.Abs(ray.Direction.Z) < 1e-7)
            {
                return(false);
            }
            thit = (_height - ray.Origin.Z) / ray.Direction.Z;
            if (thit < ray.MinT || thit > ray.MaxT)
            {
                return(false);
            }

            // See if hit point is inside disk radii and $\phimax$
            phit  = ray.Evaluate(thit);
            dist2 = phit.X * phit.X + phit.Y * phit.Y;
            if (dist2 > _radius * _radius || dist2 < _innerRadius * _innerRadius)
            {
                return(false);
            }

            // Test disk $\phi$ value against $\phimax$
            phi = MathUtility.Atan2(phit.Y, phit.X);
            if (phi < 0)
            {
                phi += 2.0f * MathUtility.Pi;
            }
            if (phi > _phiMax)
            {
                return(false);
            }

            return(true);
        }
コード例 #9
0
        public override (double?, SurfaceInteraction) Intersect(Ray r)
        {
            Ray ray = WorldToObject.Apply(r);

            var ox = ray.o.x;
            var oy = ray.o.y;
            var oz = ray.o.z;

            var dx = ray.d.x;
            var dy = ray.d.y;
            var dz = ray.d.z;

            var a = dx * dx + dy * dy + dz * dz;
            var b = 2 * (dx * ox + dy * oy + dz * oz);
            var c = ox * ox + oy * oy + oz * oz - Radius * Radius;

            var(solvable, t0, t1) = Utils.Quadratic(a, b, c);
            if (!solvable)
            {
                return(null, null);
            }

            var shapeHit = t0 <= 0 ? t1 : t0;

            var hit = ray.Point(shapeHit);

            hit *= Radius / hit.Length();

            if (Math.Abs(hit.x) < Double.Epsilon && Math.Abs(hit.y) < double.Epsilon)
            {
                hit.x = 1e-5 * Radius;
            }

            var dpdu   = Dpdu(hit);
            var normal = innerOrientation ? -hit : hit;

            var interaction = new SurfaceInteraction(hit, normal, -ray.d, dpdu, this);

            return(shapeHit, ObjectToWorld.Apply(interaction));
        }
コード例 #10
0
        public override (double?, SurfaceInteraction) Intersect(Ray ray)
        {
            Ray r = WorldToObject.Apply(ray);

            // Compute quadratic sphere coefficients

            // Initialize _double_ ray coordinate values
            double a = r.d.x * r.d.x + r.d.y * r.d.y + r.d.z * r.d.z;
            double b = 2 * (r.d.x * r.o.x + r.d.y * r.o.y + r.d.z * r.o.z);
            double c = r.o.x * r.o.x + r.o.y * r.o.y + r.o.z * r.o.z - Radius * Radius;

            // Solve quadratic equation for _t_ values
            (bool s, double t0, double t1) = Utils.Quadratic(a, b, c);

            if (!s)
            {
                return(null, null);
            }

            // Check quadric shape _t0_ and _t1_ for nearest intersection
            if (t1 <= 0)
            {
                return(null, null);
            }

            double tShapeHit = t0;

            if (tShapeHit <= Renderer.Epsilon)
            {
                tShapeHit = t1;
            }

            // Compute sphere hit position and $\phi$
            var pHit = r.Point(tShapeHit);
            var dpdu = new Vector3(-pHit.y, pHit.x, 0);
            var si   = new SurfaceInteraction(pHit, pHit.Clone().Normalize(), -r.d, dpdu, this);

            return(tShapeHit, ObjectToWorld.Apply(si));
        }
コード例 #11
0
        public override (double?, SurfaceInteraction) Intersect(Ray r)
        {
            var ray = WorldToObject.Apply(r);

            // Compute plane intersection for disk

            // Reject disk intersections for rays parallel to the disk's plane
            if (ray.d.z == 0)
            {
                return(null, null);
            }

            double tShapeHit = (height - ray.o.z) / ray.d.z;

            if (tShapeHit <= Renderer.Epsilon)
            {
                return(null, null);
            }

            // See if hit point is inside disk radii and $\phimax$
            var pHit  = ray.Point(tShapeHit);
            var dist2 = pHit.x * pHit.x + pHit.y * pHit.y;

            if (dist2 > radius * radius + Renderer.Epsilon)
            {
                return(null, null);
            }

            // Refine disk intersection point
            pHit.z = height;

            var dpdu = new Vector3(-pHit.y, pHit.x, 0);

            var si = new SurfaceInteraction(pHit, new Vector3(0, 0, 1), -ray.d, dpdu, this);

            return(tShapeHit, ObjectToWorld.Apply(si));
        }
コード例 #12
0
        private bool DoIntersection(Ray r, out float phi, out Point phit, out float thit)
        {
            phi  = 0.0f;
            phit = new Point();
            thit = 0.0f;

            // Transform _Ray_ to object space
            Ray ray = WorldToObject.TransformRay(r);

            // Compute quadratic sphere coefficients
            float A = ray.Direction.X * ray.Direction.X + ray.Direction.Y * ray.Direction.Y +
                      ray.Direction.Z * ray.Direction.Z;
            float B = 2 *
                      (ray.Direction.X * ray.Origin.X + ray.Direction.Y * ray.Origin.Y + ray.Direction.Z * ray.Origin.Z);
            float C = ray.Origin.X * ray.Origin.X + ray.Origin.Y * ray.Origin.Y +
                      ray.Origin.Z * ray.Origin.Z - _radius * _radius;

            // Solve quadratic equation for _t_ values
            float t0, t1;

            if (!MathUtility.TryQuadratic(A, B, C, out t0, out t1))
            {
                return(false);
            }

            // Compute intersection distance along ray
            if (t0 > ray.MaxT || t1 < ray.MinT)
            {
                return(false);
            }
            thit = t0;
            if (t0 < ray.MinT)
            {
                thit = t1;
                if (thit > ray.MaxT)
                {
                    return(false);
                }
            }

            // Compute sphere hit position and $\phi$
            phit = ray.Evaluate(thit);
            if (phit.X == 0.0f && phit.Y == 0.0f)
            {
                phit.X = 1e-5f * _radius;
            }
            phi = MathUtility.Atan2(phit.Y, phit.X);
            if (phi < 0.0f)
            {
                phi += 2.0f * MathUtility.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.Evaluate(thit);
                if (phit.X == 0.0f && phit.Y == 0.0f)
                {
                    phit.X = 1e-5f * _radius;
                }
                phi = MathUtility.Atan2(phit.Y, phit.X);
                if (phi < 0.0f)
                {
                    phi += 2.0f * MathUtility.Pi;
                }
                if ((_zMin > -_radius && phit.Z < _zMin) ||
                    (_zMax < _radius && phit.Z > _zMax) || phi > _phiMax)
                {
                    return(false);
                }
            }

            return(true);
        }
コード例 #13
0
ファイル: Sphere.cs プロジェクト: ZBabnik/nrg_hw2
        public override (double?, SurfaceInteraction) Intersect(Ray ray)
        {
            Ray r = WorldToObject.Apply(ray);

            // TODO: Compute quadratic sphere coefficients

            // TODO: Initialize _double_ ray coordinate values
            (double dx, double dy, double dz) = (r.d.x, r.d.y, r.d.z);
            (double ox, double oy, double oz) = (r.o.x, r.o.y, r.o.z);
            double a = dx * dx + dy * dy + dz * dz;
            double b = 2 * (dx * ox + dy * oy + dz * oz);
            double c = ox * ox + oy * oy + oz * oz - this.Radius * this.Radius;

            // TODO: Solve quadratic equation for _t_ values
            (bool zzz, double t0, double t1) = Utils.Quadratic(a, b, c);
            if (!zzz)
            {
                return(null, null);
            }

            // TODO: Check quadric shape _t0_ and _t1_ for nearest intersection
            //double tShapeHit;
            //if (t1 < Renderer.Epsilon)
            //    return (null, null);
            //if (t0 < Renderer.Epsilon)
            //    tShapeHit = t1;
            //else
            //{
            //    Ray temp = new Ray(r.o, r.d);
            //    double d1 = Vector3.Dot(temp.Point(t0), temp.o);
            //    double d2 = Vector3.Dot(temp.Point(t1), temp.o);
            //    if (d1 == d2)
            //        return (null, null);
            //    else if (d1 > d2)
            //    {
            //        if (Outside)
            //            tShapeHit = t0;
            //        else
            //            tShapeHit = t1;
            //    }
            //    else
            //    {
            //        if (Outside)
            //            tShapeHit = t1;
            //        else
            //            tShapeHit = t0;
            //    }
            //}

            //if (t1 - t0 <= Renderer.Epsilon)
            //    return (null, null);

            //Ray temp = new Ray(r.o, r.d);
            //double d0 = Vector3.Dot(temp.o, temp.Point(t0));
            //double d1 = Vector3.Dot(temp.o, temp.Point(t1));
            //double tShapeHit;

            //if (d0 >= d1)
            //    tShapeHit = t0;
            //else
            //    tShapeHit = t1;

            if (Outside)
            {
                Console.WriteLine("HERE");

                //if (t1 < Renderer.Epsilon)
                //    return (null, null);
                //double tShapeHit = t0;
                //if (tShapeHit < Renderer.Epsilon)
                //{
                //    tShapeHit = t1;
                //}

                double  tShapeHit;
                Ray     temp = new Ray(r.o, r.d);
                Vector3 p_t0 = temp.Point(t0);
                Vector3 p_t1 = temp.Point(t1);
                double  d0   = Math.Sqrt(Math.Pow(temp.o.x - p_t0.x, 2) + Math.Pow(temp.o.y - p_t0.y, 2) + Math.Pow(temp.o.z - p_t0.z, 2));
                double  d1   = Math.Sqrt(Math.Pow(temp.o.x - p_t1.x, 2) + Math.Pow(temp.o.y - p_t1.y, 2) + Math.Pow(temp.o.z - p_t1.z, 2));

                if (d0 > d1)
                {
                    tShapeHit = t1;
                }
                else
                {
                    tShapeHit = t0;
                }

                //// TODO: Compute sphere hit position and $\phi$
                Vector3 pHit = r.Point(tShapeHit);
                //pHit *= Radius / Math.Sqrt(pHit.x * pHit.x + pHit.y * pHit.y + pHit.z * pHit.z);

                //if (Math.Sqrt(pHit.x * pHit.x + pHit.y * pHit.y + pHit.z * pHit.z) >= this.Radius + Renderer.Epsilon)
                //    return (null, null);
                //if (Math.Sqrt(pHit.x * pHit.x + pHit.y * pHit.y + pHit.z * pHit.z) <= this.Radius - Renderer.Epsilon)
                //    return (null, null);

                //double phi = Math.Atan2(pHit.y, pHit.x);
                //if (phi < 0)
                //    phi += 2 * Math.PI;
                //double theta = Math.Acos(Utils.Clamp(pHit.z / this.Radius, -1, 1));

                //double invR = 1 / Math.Sqrt(pHit.x * pHit.x + pHit.y * pHit.y);
                //Vector3 n = new Vector3(pHit.z * pHit.x * invR, pHit.z * pHit.y * invR, -this.Radius * Math.Sin(theta));

                Vector3 n = (ObjectToWorld.ApplyPoint(pHit) - ObjectToWorld.ApplyPoint(Vector3.ZeroVector)).Clone().Normalize();
                //Vector3 n = new Vector3(0, 0, 1);
                //Vector3 n = pHit.Clone() * this.Radius;

                // TODO: Return shape hit and surface interaction
                Vector3 dpdu = new Vector3(-pHit.y, pHit.x, 0);

                //Console.WriteLine("dpdu1 " + dpdu.x + " " + dpdu.y + " " + dpdu.z);

                n.Faceforward(dpdu);

                //Console.WriteLine("normal " + n.x + " " + n.y + " " + n.z);

                double abDot = Vector3.Dot(n, dpdu);
                double bbDot = Vector3.Dot(n, n);

                Vector3 proj = abDot / bbDot * n;

                dpdu -= proj;

                //Console.WriteLine("proj " + proj.x + " " + proj.y + " " + proj.z);

                //Console.WriteLine("dot " + Vector3.Dot(n, dpdu));

                var si = new SurfaceInteraction(pHit, n, -ray.d, dpdu, this);
                //var si = new SurfaceInteraction(pHit, new Vector3(0, 0, 1), -ray.d, dpdu, this);


                return(tShapeHit, ObjectToWorld.Apply(si));
            }
            else
            {
                //Console.WriteLine(r.o.x + " " + r.o.y + " " + r.o.z);
                //Console.WriteLine(t0);
                //Console.WriteLine(t1);
                //System.Environment.Exit(1);

                double  tShapeHit;
                Ray     temp = new Ray(r.o, r.d);
                Vector3 p_t0 = temp.Point(t0);
                Vector3 p_t1 = temp.Point(t1);

                Vector3 x = p_t0 - temp.o;
                Vector3 y = p_t1 - temp.o;

                double x_x = Vector3.Dot(x, temp.d);
                double y_x = Vector3.Dot(y, temp.d);

                //Console.WriteLine(temp.d.x + " " + temp.d.y + " " + temp.d.z);
                //Console.WriteLine(x_x);
                //Console.WriteLine(y_x);
                //System.Environment.Exit(1);

                if (x_x > 0)
                {
                    tShapeHit = t0;
                }
                else if (y_x > 0)
                {
                    tShapeHit = t1;
                }
                else
                {
                    return(null, null);
                }

                //// TODO: Compute sphere hit position and $\phi$
                Vector3 pHit = r.Point(tShapeHit);
                //pHit *= Radius / Math.Sqrt(pHit.x * pHit.x + pHit.y * pHit.y + pHit.z * pHit.z);

                //if (Math.Sqrt(pHit.x * pHit.x + pHit.y * pHit.y + pHit.z * pHit.z) >= this.Radius + Renderer.Epsilon)
                //    return (null, null);
                //if (Math.Sqrt(pHit.x * pHit.x + pHit.y * pHit.y + pHit.z * pHit.z) <= this.Radius - Renderer.Epsilon)
                //    return (null, null);

                //double phi = Math.Atan2(pHit.y, pHit.x);
                //if (phi < 0)
                //    phi += 2 * Math.PI;
                //double theta = Math.Acos(Utils.Clamp(pHit.z / this.Radius, -1, 1));

                //double invR = 1 / Math.Sqrt(pHit.x * pHit.x + pHit.y * pHit.y);
                //Vector3 n = new Vector3(pHit.z * pHit.x * invR, pHit.z * pHit.y * invR, -this.Radius * Math.Sin(theta));

                Vector3 n = (ObjectToWorld.ApplyPoint(Vector3.ZeroVector) - ObjectToWorld.ApplyPoint(pHit)).Clone().Normalize();
                //Vector3 n = new Vector3(0, 0, 1);
                //Vector3 n = pHit.Clone() * this.Radius;

                // TODO: Return shape hit and surface interaction
                Vector3 dpdu = new Vector3(-pHit.y, pHit.x, 0);

                //Console.WriteLine("dpdu1 " + dpdu.x + " " + dpdu.y + " " + dpdu.z);

                dpdu.Faceforward(n);

                //Console.WriteLine("normal " + n.x + " " + n.y + " " + n.z);

                double abDot = Vector3.Dot(n, dpdu);
                double bbDot = Vector3.Dot(n, n);

                Vector3 proj = abDot / bbDot * n;

                dpdu -= proj;

                //Console.WriteLine("proj " + proj.x + " " + proj.y + " " + proj.z);

                //Console.WriteLine("dot " + Vector3.Dot(n, dpdu));

                var si = new SurfaceInteraction(pHit, n, -ray.d, dpdu, this);
                //var si = new SurfaceInteraction(pHit, new Vector3(0, 0, 1), -ray.d, dpdu, this);


                return(tShapeHit, ObjectToWorld.Apply(si));
            }

            // A dummy return example
            //double dummyHit = 0.0;
            //Vector3 dummyVector = new Vector3(0, 0, 0);
            //SurfaceInteraction dummySurfaceInteraction = new SurfaceInteraction(dummyVector, dummyVector, dummyVector, dummyVector, this);
            //return (dummyHit, dummySurfaceInteraction);
        }