private void build(List<Photon> points, int depth)
        {
            if (points.Count == 1)
            {
                p = points[0];
                left = null;
                right = null;
            }
            else
            {
                points.OrderBy(x => KDTree.getComponentFromDepth(x.position, depth));

                int medianIndex = points.Count / 2;
                p = points[medianIndex];
                List<Photon> leftList = points.GetRange(0, medianIndex);
                List<Photon> rightList = points.GetRange(medianIndex + 1, points.Count - medianIndex - 1);

                left = new KDTree(leftList, depth + 1);                                 //This should never be null as the case with 1 point is 
                //  taken care of above
                right = rightList.Count > 0 ? new KDTree(rightList, depth + 1) : null;  //This will be null if only 2 points                              

            }
        }
 void oneConstructor()
 {
     KDTree test = new KDTree(createList(1));
 }
 void twoConstructor()
 {
     KDTree test = new KDTree(createList(2));
 }
 void zeroConstructor()
 {
     KDTree test = new KDTree(new List<Photon>());
 }
 void longListConstructor()
 {
     KDTree test = new KDTree(createList(30000));
 }
 void oddLengthConstructor()
 {
     KDTree test = new KDTree(createList(55));
 }
 void evenLengthConstructor()
 {
     KDTree test = new KDTree(createList(40));
 }
        // Runs the light map process
        public static List<LightMap> runLightmaps(List<ModelInstance> models, List<Light> lights)
        {
            //Reset abort
            abort = false;

            //-- Get the geometry we need for lightmapping --//

            //The list of triangles which will be casting shadows, we don't care which models they come from
            List<Triangle> castingTriangles = new List<Triangle>();

            //The list of models that need lightmaps, not all models receive lightmaps
            List<ModelInstance> receivingModels = new List<ModelInstance>();

            //Find all the lightmapped models and casting triangles
            foreach (ModelInstance m in models)
            {
                if (m.baseModel.isLightmapped)
                    receivingModels.Add(m);
                if (m.baseModel.castsShadows)
                    castingTriangles.AddRange(m.tris);
            }
            Stopwatch watch;


            //-- Do the lightmapping --//

            //Make the lightmaps
            Settings.stream.WriteText("Creating maps . . . ");
            watch = Stopwatch.StartNew();
            List<LightMap> maps = makeLightmaps(receivingModels);
            watch.Stop();
            Settings.stream.WriteLine("Done ({0}ms)", watch.ElapsedMilliseconds);

            //Make the triangle partitioner
            Settings.stream.WriteText("Partitioning level . . . ");
            watch = Stopwatch.StartNew();
            TrianglePartitioner partition = new Octree(castingTriangles);
            watch.Stop();
            Settings.stream.WriteLine("Done ({0}ms)", watch.ElapsedMilliseconds);

            //Shoot the photons
            Settings.stream.WriteText("Firing photons with {0} threads, {1} photons per light . . . ", Settings.maxThreads, Settings.numPhotonsPerLight);
            watch = Stopwatch.StartNew();
            List<Photon> photons = firePhotons(lights, partition);
            watch.Stop();
            Settings.stream.WriteLine("Done ({0}ms)", watch.ElapsedMilliseconds);

            if (photons.Count > 0)
            {
                //Make the photon map
                Settings.stream.WriteText("Making photon map with {0} photons . . . ", photons.Count);
                watch = Stopwatch.StartNew();
                PhotonPartitioner photonMap = new KDTree(photons);
                watch.Stop();
                Settings.stream.WriteLine("Done ({0}ms)", watch.ElapsedMilliseconds);

                //Gather the photons for each patch in each map
                Settings.stream.WriteText("Gathering photons for lightmaps . . . ");
                watch = Stopwatch.StartNew();
                gatherPhotons(maps, photonMap, partition, lights);
                watch.Stop();
                Settings.stream.WriteLine("Done ({0}ms)", watch.ElapsedMilliseconds);
            }
            else
            {
                Settings.stream.WriteText("No lights affect the lightmaps, skipping to ambient occlusion.");
            }
            //Do Ambient Occlusion
            Settings.stream.WriteText("Calculating ambient occlusion . . . ");
            //calculateAmbientOcclusion(maps,partition);
            Settings.stream.WriteLine("Done");

            return maps;
        }