示例#1
0
        public List <double> GetIntersection(Ray ray)
        {
            //Intersection Ray / Sphere
            //Sphere eq = dot((P - c)(P - c)) = RR (P = [x, y, z], c = [cx, cy, cz])
            //Intersection then: dot((ray - c)(ray - c)) = RR ->  dot((A + Bt -C)(A+Bt-C)) = RR
            //tt*dot(B,B) +2t *dot(B, A-C ) + dot(A-C, A-C) - RR = 0;

            var oc = ray.Origin - this.Center;
            var a  = Vector3D.DotProduct(ray.Direction, ray.Direction);
            var b  = 2 * Vector3D.DotProduct(oc, ray.Direction);
            var c  = Vector3D.DotProduct(oc, oc) - this.Radius * this.Radius;

            var discriminant = b * b - 4 * a * c;

            // No solution!
            if (discriminant < 0)
            {
                return(null);
            }

            List <double> result = new List <double>();

            var temp             = Math.Sqrt(discriminant);
            var temp2            = 2 * a;
            var negativeSolution = (-b - temp) / temp2;
            var positiveSolution = (-b + temp) / temp2;

            if (negativeSolution > MinOffset && negativeSolution < MaxOffset)
            {
                result.Add(negativeSolution);
            }

            if (positiveSolution > MinOffset && positiveSolution < MaxOffset)
            {
                result.Add(positiveSolution);
            }

            return(result);
        }
示例#2
0
        /// <summary>
        /// Calculate the intesection point between the ray and the plane of the rectangle.
        /// </summary>
        /// <param name="ray">The ray to check</param>
        /// <param name="intersectionPoint">The result intersection point</param>
        /// <returns>True if the intersection is in the rectangle</returns>
        override public bool Intersects(Ray ray, ref Vector3D intersectionPoint)
        {
            var normalDotProduct = Vector3D.DotProduct(Normal, ray.Direction);

            // Do the intersection test as for a Plane.
            if (normalDotProduct != 0)
            {
                //Give the right orientation to the normal vector
                if (normalDotProduct > 0)
                {
                    normal           = -Normal;
                    normalDotProduct = -normalDotProduct;
                }

                Vector3D Point = (Vector3D)Point1;
                double   t     = (Vector3D.DotProduct(Normal, (Vector3D.Subtract(Point, ray.Source)))) / normalDotProduct;

                if (t >= 0)
                {
                    intersectionPoint = ray.Source + (ray.Direction * t);

                    var vec1 = (Point3D)intersectionPoint - Point1;
                    var vec2 = Point2 - Point1;
                    var vec3 = Point4 - Point1;

                    var alpha = Vector3D.DotProduct(vec1, vec2) / vec2.LengthSquared;
                    var beta  = Vector3D.DotProduct(vec1, vec3) / vec3.LengthSquared;

                    if (alpha >= 0 && alpha <= 1 && beta >= 0 && beta <= 1)
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
示例#3
0
        public override bool Intersects(Ray ray, ref Vector3D intersectionPoint)
        {
            double distance = double.NaN;

            Vector3D originOffset = ray.Source - Center;

            // a = 1 since  ray.D.Dot() = 1
            double b = 2.0 * (Vector3D.DotProduct(ray.Direction, originOffset));
            double c = Vector3D.DotProduct(originOffset, originOffset) - (Radius * Radius);

            double discriminant = b * b - 4.0 * c;

            if (discriminant < 0)
            {
                return(false);
            }

            // compute q as described above
            double distSqrt = Math.Sqrt(discriminant);
            double q;

            if (b > 0)
            {
                q = (-b - distSqrt) / 2.0;
            }
            else
            {
                q = (-b + distSqrt) / 2.0;
            }

            // compute t0 and t1
            double t0 = q;
            double t1 = c / q;

            // make sure t0 is smaller than t1
            if (t0 > t1)
            {
                // if t0 is bigger than t1 swap them around
                double temp = t0;
                t0 = t1;
                t1 = temp;
            }

            // if t1 is less than zero, the object is in the ray's negative direction
            // and consequently the ray misses the sphere
            if (t1 < 0)
            {
                return(false);
            }

            // if t0 is less than zero, the intersection point is at t1
            if (t0 < 0)
            {
                distance = t1;
            }
            else
            {
                // else the intersection point is at t0
                distance = t0;
            }

            intersectionPoint = ray.Source + ray.Direction * distance;

            return(true);
        }
示例#4
0
        private void GetColor(HitInfo info, Light light, ColorAccumulator colorAccu, int count)
        {
            Vector3D lightLocation = light.Location;
            Vector3D lightNormal   = info.hitPoint - lightLocation;

            lightNormal.Normalize();

            double lambert = Vector3D.DotProduct(lightNormal, info.normal);

            if (lambert <= 0)
            {
                int r, g, b;
                r = g = b = 0;

                int r2 = 0;
                int g2 = 0;
                int b2 = 0;

                info.hitObject.GetColor(info.hitPoint, ref r, ref g, ref b);

                if (info.hitObject.Material != null)
                {
                    var objectMaterial = info.hitObject.Material;

                    //Phong
                    if (objectMaterial is SolidColor)
                    {
                        if (InShadow(info, lightLocation, lightNormal))
                        {
                            return;
                        }

                        double phongTerm = Math.Pow(lambert, 20) * (objectMaterial as SolidColor).Phong * 2 * light.Intensity;
                        r2 = (int)(light.Color.R * phongTerm);
                        g2 = (int)(light.Color.G * phongTerm);
                        b2 = (int)(light.Color.B * phongTerm);

                        var intensityFactor = light.Intensity * -lambert / 255;

                        colorAccu.R += (int)(light.Color.R * r * intensityFactor) + r2;
                        colorAccu.G += (int)(light.Color.G * g * intensityFactor) + g2;
                        colorAccu.B += (int)(light.Color.B * b * intensityFactor) + b2;
                    }
                    //Reflection
                    else if (objectMaterial is Metal)
                    {
                        var metal = objectMaterial as Metal;

                        //double phongTerm = Math.Pow(lambert, 20) * 0.6 * 2 * light.Intensity;
                        //r2 = (int)(light.Color.R * phongTerm);
                        //g2 = (int)(light.Color.G * phongTerm);
                        //b2 = (int)(light.Color.B * phongTerm);

                        double   reflet    = 2.0f * (Vector3D.DotProduct(info.normal, info.ray.Direction));
                        Vector3D direction = info.ray.Direction - info.normal * reflet;
                        direction.Normalize();
                        direction += metal.Fuzz * StaticRandom.RandomVectorInUnitSphere(); //Random in cone
                        //direction.Normalize();
                        Ray reflect = new Ray(info.hitPoint + direction / 100000, direction);
                        ColorAccumulator reflectedColorAccu = CastRay(reflect, ++count);

                        if (reflectedColorAccu != null)
                        {
                            var attenuation = metal.Reflection * light.Intensity;
                            colorAccu.R += (int)(reflectedColorAccu.R * attenuation) + r2;
                            colorAccu.G += (int)(reflectedColorAccu.G * attenuation) + g2;
                            colorAccu.B += (int)(reflectedColorAccu.B * attenuation) + b2;
                        }
                    }
                }
            }
        }