public override Isect intersect(Ray ry)
 {
     double b, disc, t;
     Isect ip;
     v.sub2(c, ry.P);
     b = Vec.dot(v, ry.D);
     disc = b * b - Vec.dot(v, v) + r2;
     if (disc < 0.0)
     {
         return null;
     }
     disc = Math.Sqrt(disc);
     t = (b - disc < 1e-6) ? b + disc : b - disc;
     if (t < 1e-6)
     {
         return null;
     }
     ip = new Isect();
     ip.t = t;
     ip.enter = Vec.dot(v, v) > r2 + 1e-6 ? 1 : 0;
     ip.prim = this;
     ip.surf = surf;
     return ip;
 }
        /**
           * Returns the shaded color
           * @return The color in Vec form (rgb)
           */
        Vec shade(int level, double weight, Vec P, Vec N, Vec I, Isect hit)
        {
            double n1, n2, eta, c1, cs2;
            Vec r;
            Vec tcol;
            Vec R;
            double t, diff, spec;
            Surface surf;
            Vec col;
            int l;

            col = new Vec();
            surf = hit.surf;
            R = new Vec();
            if (surf.shine > 1e-6)
            {
                R = SpecularDirection(I, N);
            }

            // Computes the effectof each light
            for (l = 0; l < lights.Length; l++)
            {
                L.sub2(lights[l].pos, P);
                if (Vec.dot(N, L) >= 0.0)
                {
                    t = L.normalize();

                    tRay.P = P;
                    tRay.D = L;

                    // Checks if there is a shadow
                    if (Shadow(tRay, t) > 0)
                    {
                        diff = Vec.dot(N, L) * surf.kd *
                          lights[l].brightness;

                        col.adds(diff, surf.color);
                        if (surf.shine > 1e-6)
                        {
                            spec = Vec.dot(R, L);
                            if (spec > 1e-6)
                            {
                                spec = Math.Pow(spec, surf.shine);
                                col.x += spec;
                                col.y += spec;
                                col.z += spec;
                            }
                        }
                    }
                } // if
            } // for

            tRay.P = P;
            if (surf.ks * weight > 1e-3)
            {
                tRay.D = SpecularDirection(I, N);
                tcol = trace(level + 1, surf.ks * weight, tRay);
                col.adds(surf.ks, tcol);
            }
            if (surf.kt * weight > 1e-3)
            {
                if (hit.enter > 0)
                    tRay.D = TransDir(null, surf, I, N);
                else
                    tRay.D = TransDir(surf, null, I, N);
                tcol = trace(level + 1, surf.kt * weight, tRay);
                col.adds(surf.kt, tcol);
            }

            // garbaging...
            tcol = null;
            surf = null;

            return col;
        }