public override Vector Normal(Vector p)
        {
            //Assuming sphere at origin as (norm(P-C)==norm(P))
            return p.Normalize();

            //return Vector();
        }
 public Hit(Vector source, Vector d, float t, SceneObject scObject)
 {
     this.source = source;
     this.d = d;
     this.t = t;
     this.scObject = scObject;
 }
        public override float Intersect(Vector source, Vector d)
        {
            float t = (a - Vector.Dot(source, n))/Vector.Dot(d, n);

            if( (t >= 0) && (Vector.Dot(d, n) != 0) )
                return t;

            return -1;
        }
        public static float Dot(Vector f, Vector v)
        {
            /** dot product *************************************/

            float ret = 0;

            ret += v.x * f.x;
            ret += v.y * f.y;
            ret += v.z * f.z;

            return ret;
        }
        public static Vector Cross(Vector f, Vector v)
        {
            /** cross product ***********************************/

            float a=0, b=0, c=0;

            a = f.y*v.z - f.z*v.y;
            b = f.z*v.x - f.x*v.z;
            c = f.x*v.y - f.y*v.x;

            return new Vector(a, b, c);
        }
        public Vector HitPoint()
        {
            //x = x0 + t*dx		x0 = source_X, dx = direction of ray (x1 - x0)
            //y = y0 + t*dy
            //z = z0 + t*dz
            float x = source.x + t*d.x;
            float y = source.y + t*d.y;
            float z = source.z + t*d.z;

            Vector hitVect = new Vector(x, y, z);

            return hitVect;
        }
        public override float Intersect(Vector source, Vector d)
        {
            float A = Vector.Dot(d, d);
            float B = Vector.Dot(2*source, d);
            //NB C determines that this spere is positioned at the origin and has radius 1
            float C = Vector.Dot(source, source) - 1;
            if(B*B - 4*A*C <= 0) return -1;  // no hit

            float t1;
            if(B>0)   // for numerical precision
                t1 = (-B - Convert.ToSingle( Math.Sqrt(B*B - 4*A*C)) ) / (2*A);
            else
                t1 = (-B + Convert.ToSingle( Math.Sqrt(B*B - 4*A*C)) ) / (2*A);

            float t2 = C/(A*t1); // easier way to get t2

            if(t1<t2)
                return t1;  // need only closer t
            else
                return t2;
        }
        private void RayTracingLoop(int R, int C)
        {
            int increaseCount = 0;

            int len = (windowWidth * windowHeight * 3) / 10;

            int modelCount = ((R * windowWidth * 3) + C)/ len;

            if ((modelCount == 0)||(modelCount==5))
            {
                modelCount--;
            }

            //Begin loop at correct Row and Column so that different threads calculate different areas
            for (int r=R; r < R + workWidth; r++)
            {
                for (int c=0; c < windowWidth; c++)
                {
                    // construct ray through (c, r) using axis u,v,n and window constraints H,W
                    Vector d = new Vector(0, 0, 0);

                    //d = pixelPos - eye
                    //d = -Nn +W(2c/ncols -1)u +H(2r/nrows -1)v
                    d = (n * (-N) +
                        u * (W * ((2 * (float)c / windowWidth) - 1)) +
                        v * (H * ((2 * (float)r / windowHeight) - 1)));

                    // intersect ray with scene objects
                    Hit hit = intersect(eye, d);

                    // shade pixel accordingly
                    Color color = shade(hit);

                    // add a purple haze to objects in the distance
                    float hazeDistance = 8.0f;
                    if (hit.scObject != null && hit.t > hazeDistance)
                    {
                        float logDist;
                        if (this.caching)
                        {
                            // Caching for haze intensity depending upon distance from the camera
                            if (HttpRuntime.Cache.Get("colorForHitT" + hit.t.ToString()) != null)
                            {
                                color = (Color)HttpRuntime.Cache.Get("colorForHitT" + hit.t.ToString());
                            }
                            else
                            {
                                logDist = Convert.ToSingle(Math.Log((hit.t - hazeDistance) + 1));
                                if (logDist > 20)
                                    logDist = 20;
                                color = color + (new Color(0.05f, 0.01f, 0.05f)) * logDist;
                                HttpRuntime.Cache.Insert("colorForHitT" + hit.t.ToString(), color);
                            }
                        }
                        else
                        {
                            logDist = Convert.ToSingle(Math.Log((hit.t - hazeDistance) + 1));
                            if (logDist > 20)
                                logDist = 20;
                            color = color + (new Color(0.05f, 0.01f, 0.05f)) * logDist;
                        }
                    }

                    if (((r * windowWidth * 3) + c) % len == 0)
                    {
                        modelCount++;
                    }

                    try
                    {
                        //Store double array of RGB values
                        pixelArray[modelCount][((r * windowWidth) * 3) + (c * 3) + 0 - modelCount * len] = AddColor(color.r);    //Red
                        pixelArray[modelCount][((r * windowWidth) * 3) + (c * 3) + 1 - modelCount * len] = AddColor(color.g);    //Green
                        pixelArray[modelCount][((r * windowWidth) * 3) + (c * 3) + 2 - modelCount * len] = AddColor(color.b);    //Blue

                        increaseCount++;
                        if ((increaseCount == (len*2.5)) && (parallel))
                        {
                            return;
                        }
                    }
                    catch (IndexOutOfRangeException rangeEx)
                    {
                        Debug.WriteLine(((r * windowWidth) * 3) + (c * 3) + 0 - modelCount * len, "Position 1");
                        Debug.WriteLine(modelCount, "ModelCount");
                        Debug.WriteLine(rangeEx.StackTrace, "STACK TRACE");
                    }
                }
            }
        }
        Hit intersect(Vector source, Vector d)
        {
            // initially hit scObject==NULL (no hit)
            Hit hit = new Hit(source, d, -1f, null);

            // for every scObject, check if ray hits it
            for(int i=0; i<numObjects; i++) {
                float t = sceneObjects[i].Intersect(source, d);

                // 1. only use hits visible for the camera
                // 2. only overwrite hit if either there is
                //     no hit yet, or the hit is closer
                if(t>0.00001 && (hit.scObject==null || t<hit.t))
                    hit = new Hit(source, d, t, sceneObjects[i]);
            }
            return hit;
        }
 // returns the normal at the given point p
 // if p is not on the object the result is undefined
 public abstract Vector Normal(Vector p);
 // returns the t value of the closest ray-object intersection, or -1 otherwise
 public abstract float Intersect(Vector source, Vector d);
 public override Vector Normal(Vector p)
 {
     return n;
 }
 public double Distance(Vector p)
 {
     return Vector.Dot(n, p) - a;
 }
 public void Set(Vector v)
 {
     x = v.x;
     y = v.y;
     z = v.z;
 }