Exemplo n.º 1
0
        /// <summary>
        /// Impresion recursiva
        /// </summary>
        private void doPrintDebugKdTree(KdTreeNode node, int index, StringBuilder sb)
        {
            String lineas = "";

            for (int i = 0; i < index; i++)
            {
                lineas += "-";
            }

            if (node.isLeaf())
            {
                if (node.models.Length > 0)
                {
                    sb.Append(lineas + "Models [" + node.models.Length + "]" + "\n");
                }
                else
                {
                    sb.Append(lineas + "[0]" + "\n");
                }
            }
            else
            {
                sb.Append(lineas + "\n");
                index++;
                for (int i = 0; i < node.children.Length; i++)
                {
                    doPrintDebugKdTree(node.children[i], index, sb);
                }
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Corte con plano Y
        /// </summary>
        private void doSectorKdTreeY(KdTreeNode parent, Vector3 pMin, Vector3 pMax, int step,
                                     List <TgcMesh> meshes, int childIndex, float xCutValue)
        {
            //Crear listas para realizar corte
            List <TgcMesh> possitiveList = new List <TgcMesh>();
            List <TgcMesh> negativeList  = new List <TgcMesh>();

            //Y-cut
            float cutValue  = 0;
            Plane yCutPlane = getCutPlane(meshes, new Vector3(0, 1, 0), pMin.Y, pMax.Y, ref cutValue);

            splitByPlane(yCutPlane, meshes, possitiveList, negativeList);

            //recursividad de positivos con plano Z, usando resultados positivos y childIndex 0
            doSectorKdTreeZ(parent,
                            new Vector3(pMin.X, cutValue, pMin.Z),
                            pMax,
                            step, possitiveList, childIndex + 0, xCutValue, cutValue);

            //recursividad de negativos con plano Z, usando plano X negativo y childIndex 2
            doSectorKdTreeZ(parent,
                            pMin,
                            new Vector3(pMax.X, cutValue, pMax.Z),
                            step, negativeList, childIndex + 2, xCutValue, cutValue);
        }
Exemplo n.º 3
0
        /// <summary>
        /// Corte con plano X
        /// </summary>
        private void doSectorKdTreeX(KdTreeNode parent, Vector3 pMin, Vector3 pMax,
                                     int step, List <TgcMesh> meshes)
        {
            //Crear listas para realizar corte
            List <TgcMesh> possitiveList = new List <TgcMesh>();
            List <TgcMesh> negativeList  = new List <TgcMesh>();

            //X-cut
            float cutValue  = 0;
            Plane xCutPlane = getCutPlane(meshes, new Vector3(1, 0, 0), pMin.X, pMax.X, ref cutValue);

            splitByPlane(xCutPlane, meshes, possitiveList, negativeList);

            //recursividad de positivos con plano Y, usando resultados positivos y childIndex 0
            doSectorKdTreeY(parent,
                            new Vector3(cutValue, pMin.Y, pMin.Z),
                            pMax,
                            step, possitiveList, 0, cutValue);

            //recursividad de negativos con plano Y, usando resultados negativos y childIndex 4
            doSectorKdTreeY(parent,
                            pMin,
                            new Vector3(cutValue, pMax.Y, pMax.Z),
                            step, negativeList, 4, cutValue);
        }
Exemplo n.º 4
0
 /// <summary>
 /// Hacer visibles todas las meshes de un nodo
 /// </summary>
 private void selectLeafMeshes(KdTreeNode node)
 {
     TgcMesh[] models = node.models;
     foreach (TgcMesh m in models)
     {
         m.Enabled = true;
     }
 }
Exemplo n.º 5
0
        /// <summary>
        /// Imprime por consola la generacion del KdTree
        /// </summary>
        private void printDebugKdTree(KdTreeNode rootNode)
        {
            Console.WriteLine("########## KdTree DEBUG ##########");
            StringBuilder sb = new StringBuilder();

            doPrintDebugKdTree(rootNode, 0, sb);
            Console.WriteLine(sb.ToString());
            Console.WriteLine("########## FIN KdTree DEBUG ##########");
        }
Exemplo n.º 6
0
        /// <summary>
        /// Dibujar meshes que representan los sectores del KdTree
        /// </summary>
        public List<TgcDebugBox> createDebugKdTreeMeshes(KdTreeNode rootNode, TgcBoundingBox sceneBounds)
        {
            Vector3 pMax = sceneBounds.PMax;
            Vector3 pMin = sceneBounds.PMin;

            List<TgcDebugBox> debugBoxes = new List<TgcDebugBox>();
            doCreateKdTreeDebugBox(rootNode, debugBoxes,
                pMin.X, pMin.Y, pMin.Z,
                pMax.X, pMax.Y, pMax.Z, 0);

            return debugBoxes;
        }
Exemplo n.º 7
0
        /// <summary>
        /// Dibujar meshes que representan los sectores del KdTree
        /// </summary>
        public List <TgcDebugBox> createDebugKdTreeMeshes(KdTreeNode rootNode, TgcBoundingBox sceneBounds)
        {
            Vector3 pMax = sceneBounds.PMax;
            Vector3 pMin = sceneBounds.PMin;

            List <TgcDebugBox> debugBoxes = new List <TgcDebugBox>();

            doCreateKdTreeDebugBox(rootNode, debugBoxes,
                                   pMin.X, pMin.Y, pMin.Z,
                                   pMax.X, pMax.Y, pMax.Z, 0);

            return(debugBoxes);
        }
Exemplo n.º 8
0
        /// <summary>
        /// Crear nuevo KdTree
        /// </summary>
        /// <param name="modelos">Modelos a optimizar</param>
        /// <param name="sceneBounds">Límites del escenario</param>
        public void create(List<TgcMesh> modelos, TgcBoundingBox sceneBounds)
        {
            this.modelos = modelos;
            this.sceneBounds = sceneBounds;

            //Crear KdTree
            this.kdtreeRootNode = builder.crearKdTree(modelos, sceneBounds);

            //Deshabilitar todos los mesh inicialmente
            foreach (TgcMesh mesh in modelos)
            {
                mesh.Enabled = false;
            }
        }
Exemplo n.º 9
0
        /// <summary>
        /// Se fija si los hijos de un nodo no tienen mas hijos y no tienen ningun triangulo
        /// </summary>
        private bool hasEmptyChilds(KdTreeNode node)
        {
            KdTreeNode[] children = node.children;
            for (int i = 0; i < children.Length; i++)
            {
                KdTreeNode childNode = children[i];
                if (childNode.children != null || childNode.models.Length > 0)
                {
                    return(false);
                }
            }

            return(true);
        }
Exemplo n.º 10
0
        /// <summary>
        /// Crear nuevo KdTree
        /// </summary>
        /// <param name="modelos">Modelos a optimizar</param>
        /// <param name="sceneBounds">Límites del escenario</param>
        public void create(List <TgcMesh> modelos, TgcBoundingBox sceneBounds)
        {
            this.modelos     = modelos;
            this.sceneBounds = sceneBounds;

            //Crear KdTree
            this.kdtreeRootNode = builder.crearKdTree(modelos, sceneBounds);

            //Deshabilitar todos los mesh inicialmente
            foreach (TgcMesh mesh in modelos)
            {
                mesh.Enabled = false;
            }
        }
Exemplo n.º 11
0
        /// <summary>
        /// Imprime estadisticas del KdTree
        /// </summary>
        private void printEstadisticasKdTree(KdTreeNode rootNode)
        {
            Console.WriteLine("*********** KdTree Statics ***********");

            int minModels = int.MaxValue;
            int maxModels = int.MinValue;

            obtenerEstadisticas(rootNode, ref minModels, ref maxModels);

            Console.WriteLine("Minima cantidad de modelos en hoja: " + minModels);
            Console.WriteLine("Maxima cantidad de modelos en hoja: " + maxModels);


            Console.WriteLine("*********** FIN Octree Statics ************");
        }
Exemplo n.º 12
0
        private void doCreateKdTreeDebugBox(KdTreeNode node, List <TgcDebugBox> debugBoxes,
                                            float boxLowerX, float boxLowerY, float boxLowerZ,
                                            float boxUpperX, float boxUpperY, float boxUpperZ, int step)
        {
            KdTreeNode[] children = node.children;

            //Crear caja debug
            TgcDebugBox box = createDebugBox(boxLowerX, boxLowerY, boxLowerZ, boxUpperX, boxUpperY, boxUpperZ, step);

            debugBoxes.Add(box);

            //es hoja, dibujar caja
            if (children == null)
            {
            }

            //recursividad sobre hijos
            else
            {
                step++;

                float xCut = node.xCut;
                float yCut = node.yCut;
                float zCut = node.zCut;


                //000
                doCreateKdTreeDebugBox(children[0], debugBoxes, xCut, yCut, zCut, boxUpperX, boxUpperY, boxUpperZ, step);
                //001
                doCreateKdTreeDebugBox(children[1], debugBoxes, xCut, yCut, boxLowerZ, boxUpperX, boxUpperY, zCut, step);

                //010
                doCreateKdTreeDebugBox(children[2], debugBoxes, xCut, boxLowerY, zCut, boxUpperX, yCut, boxUpperZ, step);
                //011
                doCreateKdTreeDebugBox(children[3], debugBoxes, xCut, boxLowerY, boxLowerZ, boxUpperX, yCut, zCut, step);

                //100
                doCreateKdTreeDebugBox(children[4], debugBoxes, boxLowerX, yCut, zCut, xCut, boxUpperY, boxUpperZ, step);
                //101
                doCreateKdTreeDebugBox(children[5], debugBoxes, boxLowerX, yCut, boxLowerZ, xCut, boxUpperY, zCut, step);

                //110
                doCreateKdTreeDebugBox(children[6], debugBoxes, boxLowerX, boxLowerY, zCut, xCut, yCut, boxUpperZ, step);
                //111
                doCreateKdTreeDebugBox(children[7], debugBoxes, boxLowerX, boxLowerY, boxLowerZ, xCut, yCut, zCut, step);
            }
        }
Exemplo n.º 13
0
        public KdTreeNode crearKdTree(List <TgcMesh> modelos, TgcBoundingBox sceneBounds)
        {
            KdTreeNode rootNode = new KdTreeNode();

            //iniciar generacion recursiva de KdTree
            doSectorKdTreeX(rootNode, sceneBounds.PMin, sceneBounds.PMax, 0, modelos);

            //podar nodos innecesarios
            optimizeSectorKdTree(rootNode.children);

            //imprimir por consola el KdTree
            //printDebugKdTree(rootNode);

            //imprimir estadisticas de debug
            //printEstadisticasKdTree(rootNode);

            return(rootNode);
        }
Exemplo n.º 14
0
        public KdTreeNode crearKdTree(List<TgcMesh> modelos, TgcBoundingBox sceneBounds)
        {
            KdTreeNode rootNode = new KdTreeNode();

            //iniciar generacion recursiva de KdTree
            doSectorKdTreeX(rootNode, sceneBounds.PMin, sceneBounds.PMax, 0, modelos);

            //podar nodos innecesarios
            optimizeSectorKdTree(rootNode.children);

            //imprimir por consola el KdTree
            //printDebugKdTree(rootNode);

            //imprimir estadisticas de debug
            //printEstadisticasKdTree(rootNode);

            return rootNode;
        }
Exemplo n.º 15
0
        /// <summary>
        /// Hacer visibles todas las meshes de un nodo, buscando recursivamente sus hojas
        /// </summary>
        private void addAllLeafMeshes(KdTreeNode node)
        {
            KdTreeNode[] children = node.children;

            //es hoja, cargar todos los meshes
            if (children == null)
            {
                selectLeafMeshes(node);

                //pedir hojas a hijos
            }
            else
            {
                for (int i = 0; i < children.Length; i++)
                {
                    addAllLeafMeshes(children[i]);
                }
            }
        }
Exemplo n.º 16
0
        /// <summary>
        /// Recorrer recursivamente el KdTree para encontrar los nodos visibles
        /// </summary>
        private void findVisibleMeshes(TgcFrustum frustum, KdTreeNode node,
                                       float boxLowerX, float boxLowerY, float boxLowerZ,
                                       float boxUpperX, float boxUpperY, float boxUpperZ)
        {
            KdTreeNode[] children = node.children;

            //es hoja, cargar todos los meshes
            if (children == null)
            {
                selectLeafMeshes(node);
            }

            //recursividad sobre hijos
            else
            {
                float xCut = node.xCut;
                float yCut = node.yCut;
                float zCut = node.zCut;

                //000
                testChildVisibility(frustum, children[0], xCut, yCut, zCut, boxUpperX, boxUpperY, boxUpperZ);
                //001
                testChildVisibility(frustum, children[1], xCut, yCut, boxLowerZ, boxUpperX, boxUpperY, zCut);

                //010
                testChildVisibility(frustum, children[2], xCut, boxLowerY, zCut, boxUpperX, yCut, boxUpperZ);
                //011
                testChildVisibility(frustum, children[3], xCut, boxLowerY, boxLowerZ, boxUpperX, yCut, zCut);

                //100
                testChildVisibility(frustum, children[4], boxLowerX, yCut, zCut, xCut, boxUpperY, boxUpperZ);
                //101
                testChildVisibility(frustum, children[5], boxLowerX, yCut, boxLowerZ, xCut, boxUpperY, zCut);

                //110
                testChildVisibility(frustum, children[6], boxLowerX, boxLowerY, zCut, xCut, yCut, boxUpperZ);
                //111
                testChildVisibility(frustum, children[7], boxLowerX, boxLowerY, boxLowerZ, xCut, yCut, zCut);
            }
        }
Exemplo n.º 17
0
        /// <summary>
        /// Hacer visible las meshes de un nodo si es visible por el Frustum
        /// </summary>
        private void testChildVisibility(TgcFrustum frustum, KdTreeNode childNode,
                                         float boxLowerX, float boxLowerY, float boxLowerZ, float boxUpperX, float boxUpperY, float boxUpperZ)
        {
            //test frustum-box intersection
            TgcBoundingBox caja = new TgcBoundingBox(
                new Vector3(boxLowerX, boxLowerY, boxLowerZ),
                new Vector3(boxUpperX, boxUpperY, boxUpperZ));

            TgcCollisionUtils.FrustumResult c = TgcCollisionUtils.classifyFrustumAABB(frustum, caja);

            //complementamente adentro: cargar todos los hijos directamente, sin testeos
            if (c == TgcCollisionUtils.FrustumResult.INSIDE)
            {
                addAllLeafMeshes(childNode);
            }

            //parte adentro: seguir haciendo testeos con hijos
            else if (c == TgcCollisionUtils.FrustumResult.INTERSECT)
            {
                findVisibleMeshes(frustum, childNode, boxLowerX, boxLowerY, boxLowerZ, boxUpperX, boxUpperY, boxUpperZ);
            }
        }
Exemplo n.º 18
0
        /// <summary>
        /// Se quitan padres cuyos nodos no tengan ningun triangulo
        /// </summary>
        private void optimizeSectorKdTree(KdTreeNode[] children)
        {
            if (children == null)
            {
                return;
            }

            for (int i = 0; i < children.Length; i++)
            {
                KdTreeNode   childNode         = children[i];
                KdTreeNode[] childNodeChildren = childNode.children;
                if (childNodeChildren != null && hasEmptyChilds(childNode))
                {
                    childNode.children = null;
                    childNode.models   = new TgcMesh[0];
                }
                else
                {
                    optimizeSectorKdTree(childNodeChildren);
                }
            }
        }
Exemplo n.º 19
0
 private void obtenerEstadisticas(KdTreeNode node, ref int minModels, ref int maxModels)
 {
     if (node.isLeaf())
     {
         int n = node.models.Length;
         if (n < minModels)
         {
             minModels = n;
         }
         if (n > maxModels)
         {
             maxModels = n;
         }
     }
     else
     {
         for (int i = 0; i < node.children.Length; i++)
         {
             obtenerEstadisticas(node.children[i], ref minModels, ref maxModels);
         }
     }
 }
Exemplo n.º 20
0
        /// <summary>
        /// Corte con plano X
        /// </summary>
        private void doSectorKdTreeX(KdTreeNode parent, Vector3 pMin, Vector3 pMax,
            int step, List<TgcMesh> meshes)
        {
            //Crear listas para realizar corte
            List<TgcMesh> possitiveList = new List<TgcMesh>();
            List<TgcMesh> negativeList = new List<TgcMesh>();

            //X-cut
            float cutValue = 0;
            Plane xCutPlane = getCutPlane(meshes, new Vector3(1, 0, 0), pMin.X, pMax.X, ref cutValue);
            splitByPlane(xCutPlane, meshes, possitiveList, negativeList);

            //recursividad de positivos con plano Y, usando resultados positivos y childIndex 0
            doSectorKdTreeY(parent,
                    new Vector3(cutValue, pMin.Y, pMin.Z),
                    pMax,
                    step, possitiveList, 0, cutValue);

            //recursividad de negativos con plano Y, usando resultados negativos y childIndex 4
            doSectorKdTreeY(parent,
                    pMin,
                    new Vector3(cutValue, pMax.Y, pMax.Z),
                    step, negativeList, 4, cutValue);
        }
Exemplo n.º 21
0
        /// <summary>
        /// Corte con plano Y
        /// </summary>
        private void doSectorKdTreeY(KdTreeNode parent, Vector3 pMin, Vector3 pMax, int step,
            List<TgcMesh> meshes, int childIndex, float xCutValue)
        {
            //Crear listas para realizar corte
            List<TgcMesh> possitiveList = new List<TgcMesh>();
            List<TgcMesh> negativeList = new List<TgcMesh>();

            //Y-cut
            float cutValue = 0;
            Plane yCutPlane = getCutPlane(meshes, new Vector3(0, 1, 0), pMin.Y, pMax.Y, ref cutValue);
            splitByPlane(yCutPlane, meshes, possitiveList, negativeList);

            //recursividad de positivos con plano Z, usando resultados positivos y childIndex 0
            doSectorKdTreeZ(parent,
                    new Vector3(pMin.X, cutValue, pMin.Z),
                    pMax,
                    step, possitiveList, childIndex + 0, xCutValue, cutValue);

            //recursividad de negativos con plano Z, usando plano X negativo y childIndex 2
            doSectorKdTreeZ(parent,
                    pMin,
                    new Vector3(pMax.X, cutValue, pMax.Z),
                    step, negativeList, childIndex + 2, xCutValue, cutValue);
        }
Exemplo n.º 22
0
        private void doCreateKdTreeDebugBox(KdTreeNode node, List<TgcDebugBox> debugBoxes,
            float boxLowerX, float boxLowerY, float boxLowerZ,
            float boxUpperX, float boxUpperY, float boxUpperZ, int step)
        {
            KdTreeNode[] children = node.children;

            //Crear caja debug
            TgcDebugBox box = createDebugBox(boxLowerX, boxLowerY, boxLowerZ, boxUpperX, boxUpperY, boxUpperZ, step);
            debugBoxes.Add(box);

            //es hoja, dibujar caja
            if (children == null)
            {

            }

            //recursividad sobre hijos
            else
            {
                step++;

                float xCut = node.xCut;
                float yCut = node.yCut;
                float zCut = node.zCut;

                //000
                doCreateKdTreeDebugBox(children[0], debugBoxes, xCut, yCut, zCut, boxUpperX, boxUpperY, boxUpperZ, step);
                //001
                doCreateKdTreeDebugBox(children[1], debugBoxes, xCut, yCut, boxLowerZ, boxUpperX, boxUpperY, zCut, step);

                //010
                doCreateKdTreeDebugBox(children[2], debugBoxes, xCut, boxLowerY, zCut, boxUpperX, yCut, boxUpperZ, step);
                //011
                doCreateKdTreeDebugBox(children[3], debugBoxes, xCut, boxLowerY, boxLowerZ, boxUpperX, yCut, zCut, step);

                //100
                doCreateKdTreeDebugBox(children[4], debugBoxes, boxLowerX, yCut, zCut, xCut, boxUpperY, boxUpperZ, step);
                //101
                doCreateKdTreeDebugBox(children[5], debugBoxes, boxLowerX, yCut, boxLowerZ, xCut, boxUpperY, zCut, step);

                //110
                doCreateKdTreeDebugBox(children[6], debugBoxes, boxLowerX, boxLowerY, zCut, xCut, yCut, boxUpperZ, step);
                //111
                doCreateKdTreeDebugBox(children[7], debugBoxes, boxLowerX, boxLowerY, boxLowerZ, xCut, yCut, zCut, step);
            }
        }
Exemplo n.º 23
0
        /// <summary>
        /// Impresion recursiva
        /// </summary>
        private void doPrintDebugKdTree(KdTreeNode node, int index, StringBuilder sb)
        {
            String lineas = "";
            for (int i = 0; i < index; i++)
            {
                lineas += "-";
            }

            if (node.isLeaf())
            {
                if (node.models.Length > 0)
                {
                    sb.Append(lineas + "Models [" + node.models.Length + "]" + "\n");
                }
                else
                {
                    sb.Append(lineas + "[0]" + "\n");
                }

            }
            else
            {
                sb.Append(lineas + "\n");
                index++;
                for (int i = 0; i < node.children.Length; i++)
                {
                    doPrintDebugKdTree(node.children[i], index, sb);
                }
            }
        }
Exemplo n.º 24
0
        /// <summary>
        /// Corte de plano Z
        /// </summary>
        private void doSectorKdTreeZ(KdTreeNode parent, Vector3 pMin, Vector3 pMax, int step,
            List<TgcMesh> meshes, int childIndex, float xCutValue, float yCutValue)
        {
            //Crear listas para realizar corte
            List<TgcMesh> possitiveList = new List<TgcMesh>();
            List<TgcMesh> negativeList = new List<TgcMesh>();

            //Z-cut
            float cutValue = 0;
            Plane zCutPlane = getCutPlane(meshes, new Vector3(0, 0, 1), pMin.Z, pMax.Z, ref cutValue);
            splitByPlane(zCutPlane, meshes, possitiveList, negativeList);

            //obtener lista de children del parent, con iniciacion lazy
            if (parent.children == null)
            {
                parent.children = new KdTreeNode[8];
            }

            //crear nodo positivo en parent, segun childIndex
            KdTreeNode posNode = new KdTreeNode();
            parent.children[childIndex] = posNode;

            //cargar nodo negativo en parent, segun childIndex
            KdTreeNode negNode = new KdTreeNode();
            parent.children[childIndex + 1] = negNode;

            //cargar cortes en parent
            parent.xCut = xCutValue;
            parent.yCut = yCutValue;
            parent.zCut = cutValue;

            //nuevos limites
            Vector3 v1 = new Vector3(pMax.X - pMin.X, pMax.Y - pMin.Y, pMax.Z - cutValue);
            Vector3 v2 = new Vector3(pMax.X - pMin.X, pMax.Y - pMin.Y, cutValue - pMin.Z);

            //condicion de corte
            if (step >= MAX_SECTOR_KDTREE_RECURSION || meshes.Count <= MIN_MESH_PER_LEAVE_THRESHOLD
                || v1.X < MIN_VOL || v1.Y < MIN_VOL || v1.Z < MIN_VOL
                || v2.X < MIN_VOL || v2.Y < MIN_VOL || v2.Z < MIN_VOL
                )
            {
                //cargar hijos de nodo positivo
                posNode.models = possitiveList.ToArray();

                //cargar hijos de nodo negativo
                negNode.models = negativeList.ToArray();

            }
            //seguir recursividad
            else
            {
                step++;

                //recursividad de positivos con plano X, usando resultados positivos
                doSectorKdTreeX(posNode,
                        new Vector3(pMin.X, pMin.Y, cutValue),
                        pMax,
                        step, possitiveList);

                //recursividad de negativos con plano Y, usando resultados negativos
                doSectorKdTreeX(negNode,
                        pMin,
                        new Vector3(pMax.X, pMax.Y, cutValue),
                        step, negativeList);
            }
        }
Exemplo n.º 25
0
        /// <summary>
        /// Se fija si los hijos de un nodo no tienen mas hijos y no tienen ningun triangulo
        /// </summary>
        private bool hasEmptyChilds(KdTreeNode node)
        {
            KdTreeNode[] children = node.children;
            for (int i = 0; i < children.Length; i++)
            {
                KdTreeNode childNode = children[i];
                if (childNode.children != null || childNode.models.Length > 0)
                {
                    return false;
                }
            }

            return true;
        }
Exemplo n.º 26
0
 /// <summary>
 /// Hacer visibles todas las meshes de un nodo
 /// </summary>
 private void selectLeafMeshes(KdTreeNode node)
 {
     TgcMesh[] models = node.models;
     foreach (TgcMesh m in models)
     {
         m.Enabled = true;
     }
 }
Exemplo n.º 27
0
        /// <summary>
        /// Se quitan padres cuyos nodos no tengan ningun triangulo
        /// </summary>
        private void optimizeSectorKdTree(KdTreeNode[] children)
        {
            if (children == null)
            {
                return;
            }

            for (int i = 0; i < children.Length; i++)
            {
                KdTreeNode childNode = children[i];
                KdTreeNode[] childNodeChildren = childNode.children;
                if (childNodeChildren != null && hasEmptyChilds(childNode))
                {
                    childNode.children = null;
                    childNode.models = new TgcMesh[0];
                }
                else
                {
                    optimizeSectorKdTree(childNodeChildren);
                }
            }
        }
Exemplo n.º 28
0
        /// <summary>
        /// Corte de plano Z
        /// </summary>
        private void doSectorKdTreeZ(KdTreeNode parent, Vector3 pMin, Vector3 pMax, int step,
                                     List <TgcMesh> meshes, int childIndex, float xCutValue, float yCutValue)
        {
            //Crear listas para realizar corte
            List <TgcMesh> possitiveList = new List <TgcMesh>();
            List <TgcMesh> negativeList  = new List <TgcMesh>();

            //Z-cut
            float cutValue  = 0;
            Plane zCutPlane = getCutPlane(meshes, new Vector3(0, 0, 1), pMin.Z, pMax.Z, ref cutValue);

            splitByPlane(zCutPlane, meshes, possitiveList, negativeList);

            //obtener lista de children del parent, con iniciacion lazy
            if (parent.children == null)
            {
                parent.children = new KdTreeNode[8];
            }

            //crear nodo positivo en parent, segun childIndex
            KdTreeNode posNode = new KdTreeNode();

            parent.children[childIndex] = posNode;

            //cargar nodo negativo en parent, segun childIndex
            KdTreeNode negNode = new KdTreeNode();

            parent.children[childIndex + 1] = negNode;

            //cargar cortes en parent
            parent.xCut = xCutValue;
            parent.yCut = yCutValue;
            parent.zCut = cutValue;

            //nuevos limites
            Vector3 v1 = new Vector3(pMax.X - pMin.X, pMax.Y - pMin.Y, pMax.Z - cutValue);
            Vector3 v2 = new Vector3(pMax.X - pMin.X, pMax.Y - pMin.Y, cutValue - pMin.Z);

            //condicion de corte
            if (step >= MAX_SECTOR_KDTREE_RECURSION || meshes.Count <= MIN_MESH_PER_LEAVE_THRESHOLD ||
                v1.X < MIN_VOL || v1.Y < MIN_VOL || v1.Z < MIN_VOL ||
                v2.X < MIN_VOL || v2.Y < MIN_VOL || v2.Z < MIN_VOL
                )
            {
                //cargar hijos de nodo positivo
                posNode.models = possitiveList.ToArray();

                //cargar hijos de nodo negativo
                negNode.models = negativeList.ToArray();
            }
            //seguir recursividad
            else
            {
                step++;

                //recursividad de positivos con plano X, usando resultados positivos
                doSectorKdTreeX(posNode,
                                new Vector3(pMin.X, pMin.Y, cutValue),
                                pMax,
                                step, possitiveList);

                //recursividad de negativos con plano Y, usando resultados negativos
                doSectorKdTreeX(negNode,
                                pMin,
                                new Vector3(pMax.X, pMax.Y, cutValue),
                                step, negativeList);
            }
        }
Exemplo n.º 29
0
        /// <summary>
        /// Hacer visibles todas las meshes de un nodo, buscando recursivamente sus hojas
        /// </summary>
        private void addAllLeafMeshes(KdTreeNode node)
        {
            KdTreeNode[] children = node.children;

            //es hoja, cargar todos los meshes
            if (children == null)
            {
                selectLeafMeshes(node);

                //pedir hojas a hijos
            }
            else
            {
                for (int i = 0; i < children.Length; i++)
                {
                    addAllLeafMeshes(children[i]);
                }
            }
        }
Exemplo n.º 30
0
 /// <summary>
 /// Imprime por consola la generacion del KdTree
 /// </summary>
 private void printDebugKdTree(KdTreeNode rootNode)
 {
     Console.WriteLine("########## KdTree DEBUG ##########");
     StringBuilder sb = new StringBuilder();
     doPrintDebugKdTree(rootNode, 0, sb);
     Console.WriteLine(sb.ToString());
     Console.WriteLine("########## FIN KdTree DEBUG ##########");
 }
Exemplo n.º 31
0
        /// <summary>
        /// Hacer visible las meshes de un nodo si es visible por el Frustum
        /// </summary>
        private void testChildVisibility(TgcFrustum frustum, KdTreeNode childNode,
            float boxLowerX, float boxLowerY, float boxLowerZ, float boxUpperX, float boxUpperY, float boxUpperZ)
        {
            //test frustum-box intersection
            TgcBoundingBox caja = new TgcBoundingBox(
                new Vector3(boxLowerX, boxLowerY, boxLowerZ),
                new Vector3(boxUpperX, boxUpperY, boxUpperZ));
            TgcCollisionUtils.FrustumResult c = TgcCollisionUtils.classifyFrustumAABB(frustum, caja);

            //complementamente adentro: cargar todos los hijos directamente, sin testeos
            if (c == TgcCollisionUtils.FrustumResult.INSIDE)
            {
                addAllLeafMeshes(childNode);
            }

            //parte adentro: seguir haciendo testeos con hijos
            else if (c == TgcCollisionUtils.FrustumResult.INTERSECT)
            {
                findVisibleMeshes(frustum, childNode, boxLowerX, boxLowerY, boxLowerZ, boxUpperX, boxUpperY, boxUpperZ);
            }
        }
Exemplo n.º 32
0
 private void obtenerEstadisticas(KdTreeNode node, ref int minModels, ref int maxModels)
 {
     if (node.isLeaf())
     {
         int n = node.models.Length;
         if (n < minModels)
             minModels = n;
         if (n > maxModels)
             maxModels = n;
     }
     else
     {
         for (int i = 0; i < node.children.Length; i++)
         {
             obtenerEstadisticas(node.children[i], ref minModels, ref maxModels);
         }
     }
 }
Exemplo n.º 33
0
        /// <summary>
        /// Recorrer recursivamente el KdTree para encontrar los nodos visibles
        /// </summary>
        private void findVisibleMeshes(TgcFrustum frustum, KdTreeNode node,
            float boxLowerX, float boxLowerY, float boxLowerZ,
            float boxUpperX, float boxUpperY, float boxUpperZ)
        {
            KdTreeNode[] children = node.children;

            //es hoja, cargar todos los meshes
            if (children == null)
            {
                selectLeafMeshes(node);
            }

            //recursividad sobre hijos
            else
            {
                float xCut = node.xCut;
                float yCut = node.yCut;
                float zCut = node.zCut;

                //000
                testChildVisibility(frustum, children[0], xCut, yCut, zCut, boxUpperX, boxUpperY, boxUpperZ);
                //001
                testChildVisibility(frustum, children[1], xCut, yCut, boxLowerZ, boxUpperX, boxUpperY, zCut);

                //010
                testChildVisibility(frustum, children[2], xCut, boxLowerY, zCut, boxUpperX, yCut, boxUpperZ);
                //011
                testChildVisibility(frustum, children[3], xCut, boxLowerY, boxLowerZ, boxUpperX, yCut, zCut);

                //100
                testChildVisibility(frustum, children[4], boxLowerX, yCut, zCut, xCut, boxUpperY, boxUpperZ);
                //101
                testChildVisibility(frustum, children[5], boxLowerX, yCut, boxLowerZ, xCut, boxUpperY, zCut);

                //110
                testChildVisibility(frustum, children[6], boxLowerX, boxLowerY, zCut, xCut, yCut, boxUpperZ);
                //111
                testChildVisibility(frustum, children[7], boxLowerX, boxLowerY, boxLowerZ, xCut, yCut, zCut);

            }
        }
Exemplo n.º 34
0
        /// <summary>
        /// Imprime estadisticas del KdTree
        /// </summary>
        private void printEstadisticasKdTree(KdTreeNode rootNode)
        {
            Console.WriteLine("*********** KdTree Statics ***********");

            int minModels = int.MaxValue;
            int maxModels = int.MinValue;

            obtenerEstadisticas(rootNode, ref minModels, ref maxModels);

            Console.WriteLine("Minima cantidad de modelos en hoja: " + minModels);
            Console.WriteLine("Maxima cantidad de modelos en hoja: " + maxModels);

            Console.WriteLine("*********** FIN Octree Statics ************");
        }