private void build(List<Triangle> triangles, int maxTriangles, int maxDepth, BoundingBox box)
        {
            bounds = box;

            if (triangles.Count <= maxTriangles || maxDepth == 0)
            {
                tris = triangles.ToArray();
                count = tris.Length;
            }
            else
            {
                children = new Octree[8];
                count = 0;
                BoundingBox newBox;
                List<Triangle> childrenTriangles;
                List<Triangle> used = new List<Triangle>();
                Vector3 lengths = (bounds.max - bounds.min) / 2;
                Vector3 halfLengths = lengths / 2;
                for (int i = 0; i < 8; i++)
                {
                    childrenTriangles = new List<Triangle>();
                    Vector3 ooffset = Vector3.Multiply(lengths, offsets[i]);
                    newBox = new BoundingBox(bounds.center + ooffset, halfLengths.X, halfLengths.Y, halfLengths.Z);
                    foreach (Triangle t in triangles)
                    {
                        if (newBox.triangleIntersects(t))
                        {
                            childrenTriangles.Add(t);
                        }
                    }
                    
                    children[i] = new Octree(childrenTriangles, maxTriangles, maxDepth - 1, newBox);
                    count += children[i].count;
                }
            }
        }
        private void build(List <Triangle> triangles, int maxTriangles, int maxDepth, BoundingBox box)
        {
            bounds = box;

            if (triangles.Count <= maxTriangles || maxDepth == 0)
            {
                tris  = triangles.ToArray();
                count = tris.Length;
            }
            else
            {
                children = new Octree[8];
                count    = 0;
                BoundingBox     newBox;
                List <Triangle> childrenTriangles;
                List <Triangle> used        = new List <Triangle>();
                Vector3         lengths     = (bounds.max - bounds.min) / 2;
                Vector3         halfLengths = lengths / 2;
                for (int i = 0; i < 8; i++)
                {
                    childrenTriangles = new List <Triangle>();
                    Vector3 ooffset = Vector3.Multiply(lengths, offsets[i]);
                    newBox = new BoundingBox(bounds.center + ooffset, halfLengths.X, halfLengths.Y, halfLengths.Z);
                    foreach (Triangle t in triangles)
                    {
                        if (newBox.triangleIntersects(t))
                        {
                            childrenTriangles.Add(t);
                        }
                    }

                    children[i] = new Octree(childrenTriangles, maxTriangles, maxDepth - 1, newBox);
                    count      += children[i].count;
                }
            }
        }
        // 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;
        }
        private void btn_load_Click(object sender, EventArgs e)
        {
            setButtons(false);
            String filePath = tb_path.Text;
            file = filePath;
            String extention = Path.GetExtension(filePath);
            List<Mesh> renderableMeshes = new List<Mesh>();
            drawString = "File: " + file;

            updateBitmap(drawString);

            //Try and find the model file
            if (extention == ".mmh")
            {
                GFF tempGFF = new GFF(filePath);
                ModelHierarchy mh = new ModelHierarchy(tempGFF);
                currentlyShowing = Showing.Model;
                meshes = mh.mesh.toModel().meshes;
                setButtons(true);
                if (meshes.Length > 0)
                {
                    setMeshNum(0);
                }
            }
            else if (extention == ".msh")
            {
                GFF tempGFF = new GFF(filePath);
                ModelMesh mm = new ModelMesh(tempGFF);
                currentlyShowing = Showing.Model;
                meshes = mm.toModel().meshes;
                setButtons(true);
                if (meshes.Length > 0)
                {
                    setMeshNum(0);
                }
            }
            else if (extention == ".tga")
            {
                texture = new Targa(filePath);
                currentlyShowing = Showing.Texture;
            }
            else if (extention == ".lvl")
            {
                level = new LevelScene(filePath);
                currentlyShowing = Showing.Level;
                List<Patch> patchList = new List<Patch>();
                List<Triangle> tris = new List<Triangle>();
                foreach (ModelInstance m in level.lightmapModels)
                {
                    for (int i = 0; i < m.meshes.Length; i++)
                    {
                        if (m.meshes[i].isLightmapped)
                        {
                            //Make the lightmap
                            LightMap temp = new LightMap(m, m.meshes[i]);
                            //For each patch instance in the lightmap
                            foreach (Patch p in temp.patches)
                            {
                                patchList.Add(p);
                            }
                        }
                    }
                    if (m.baseModel.castsShadows)
                        tris.AddRange(m.tris);
                }
                octree = new Octree(tris);
                patches = patchList.ToArray();
            }
            else if (extention == ".xml")
            {
                level = new XMLScene(filePath);
                currentlyShowing = Showing.Level;
                List<Patch> patchList = new List<Patch>();
                List<Triangle> tris = new List<Triangle>();
                foreach (ModelInstance m in level.lightmapModels)
                {
                    for (int i = 0; i < m.meshes.Length; i++)
                    {
                        if (m.meshes[i].isLightmapped)
                        {
                            //Make the lightmap
                            LightMap temp = new LightMap(m, m.meshes[i]);
                            //For each patch instance in the lightmap
                            foreach (Patch p in temp.patches)
                            {
                                patchList.Add(p);
                            }
                        }
                    }
                    if (m.baseModel.castsShadows)
                        tris.AddRange(m.tris);
                }
                octree = new Octree(tris);
                patches = patchList.ToArray();
            }
            //If its not the right type of file then print an error
            else
            {
                drawString = "This is not a valid model (.mmh or .msh), texture (.tga), level (.lvl), or scene (.xml) file!";
            }
            refreshView();
        }