Ejemplo n.º 1
0
        /// <summary>
        ///     Impresion recursiva
        /// </summary>
        private void doPrintDebugQuadtree(QuadtreeNode node, int index, StringBuilder sb)
        {
            var lineas = "";

            for (var 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 (var i = 0; i < node.children.Length; i++)
                {
                    doPrintDebugQuadtree(node.children[i], index, sb);
                }
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        ///     Imprime por consola la generacion del Octree
        /// </summary>
        private void printDebugQuadtree(QuadtreeNode rootNode)
        {
            Console.WriteLine("########## Quadtree DEBUG ##########");
            var sb = new StringBuilder();

            doPrintDebugQuadtree(rootNode, 0, sb);
            Console.WriteLine(sb.ToString());
            Console.WriteLine("########## FIN Quadtree DEBUG ##########");
        }
Ejemplo n.º 3
0
        /// <summary>
        ///     Corte de plano Z
        /// </summary>
        private void doSectorQuadtreeZ(QuadtreeNode parent, Vector3 center, Vector3 size, int step,
                                       List <TgcMesh> meshes, int childIndex)
        {
            var z = center.Z;

            //Crear listas para realizar corte
            var possitiveList = new List <TgcMesh>();
            var negativeList  = new List <TgcMesh>();

            //Z-cut
            var zCutPlane = new Plane(0, 0, 1, -z);

            splitByPlane(zCutPlane, meshes, possitiveList, negativeList);

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

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

            parent.children[childIndex] = posNode;

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

            parent.children[childIndex + 1] = negNode;

            //condicion de corte
            if (step > MAX_SECTOR_QUADTREE_RECURSION || meshes.Count < MIN_MESH_PER_LEAVE_THRESHOLD)
            {
                //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
                doSectorQuadtreeX(posNode, new Vector3(center.X, center.Y, z + size.Z / 2),
                                  new Vector3(size.X, size.Y, size.Z / 2),
                                  step, possitiveList);

                //recursividad de negativos con plano Y, usando resultados negativos
                doSectorQuadtreeX(negNode, new Vector3(center.X, center.Y, z - size.Z / 2),
                                  new Vector3(size.X, size.Y, size.Z / 2),
                                  step, negativeList);
            }
        }
Ejemplo n.º 4
0
        /// <summary>
        ///     Hacer visibles todas las meshes de un nodo
        /// </summary>
        private void selectLeafMeshes(QuadtreeNode node, int contador)
        {
            var models = node.models;

            foreach (var m in models)
            {
                m.Enabled = true;

                if (contador == 0)
                {
                    foreach (var unAuto in GameModel.ListaMeshAutos)
                    {
                        if ((m.Name != "Room-1-Roof-0") && (m.Name != "Room-1-Floor-0") &&
                            (m.Name != "Pasto") && (m.Name != "Plane_5"))
                        {
                            //me fijo si hubo alguna colision
                            if (TgcCollisionUtils.testObbAABB(unAuto.ObbMesh, m.BoundingBox))
                            {
                                if (m.Name.IndexOf("PowerUp Vida") != -1)
                                {
                                    m.Enabled = false;

                                    if (modelos.IndexOf(m) != -1)
                                    {
                                        modelos.Remove(m);
                                        unAuto.ModificadorVida += 4f;
                                        unAuto.ReproducirSonidoPowerUpVida();
                                    }

                                    unAuto.colisiono = false;

                                    continue;
                                }

                                unAuto.meshColisionado = m;
                                unAuto.colisiono       = true;

                                if ((m.Name.IndexOf("Palmera") != -1) || (m.Name.IndexOf("Pino") != -1) || (m.Name.IndexOf("ArbolBananas") != -1))
                                {
                                    unAuto.ModificadorVida = -5;
                                }

                                if ((m.Name.IndexOf("Roca") != -1) || (m.Name.IndexOf("Estructura") != -1) || (m.Name.IndexOf("Glorieta") != -1))
                                {
                                    unAuto.ModificadorVida = -2.5f;
                                }
                            }
                        }
                    }
                }
            }
        }
Ejemplo n.º 5
0
        /// <summary>
        ///     Dibujar meshes que representan los sectores del Quadtree
        /// </summary>
        public List <TgcBoxDebug> createDebugQuadtreeMeshes(QuadtreeNode rootNode, TgcBoundingAxisAlignBox sceneBounds)
        {
            var pMax = sceneBounds.PMax;
            var pMin = sceneBounds.PMin;

            var debugBoxes = new List <TgcBoxDebug>();

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

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

            //Crear Quadtree
            quadtreeRootNode = builder.crearQuadtree(modelos, sceneBounds);

            //Deshabilitar todos los mesh inicialmente
            foreach (var mesh in modelos)
            {
                mesh.Enabled = false;
            }
        }
Ejemplo n.º 7
0
        /// <summary>
        ///     Imprime estadisticas del Octree
        /// </summary>
        private void printEstadisticasQuadtree(QuadtreeNode rootNode)
        {
            Console.WriteLine("*********** Quadtree Statics ***********");

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

            obtenerEstadisticas(rootNode, ref minModels, ref maxModels);

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

            Console.WriteLine("*********** FIN Quadtree Statics ************");
        }
Ejemplo n.º 8
0
        /// <summary>
        ///     Se fija si los hijos de un nodo no tienen mas hijos y no tienen ningun triangulo
        /// </summary>
        private bool hasEmptyChilds(QuadtreeNode node)
        {
            var children = node.children;

            for (var i = 0; i < children.Length; i++)
            {
                var childNode = children[i];
                if (childNode.children != null || childNode.models.Length > 0)
                {
                    return(false);
                }
            }

            return(true);
        }
Ejemplo n.º 9
0
        /// <summary>
        ///     Hacer visibles todas las meshes de un nodo, buscando recursivamente sus hojas
        /// </summary>
        private void addAllLeafMeshes(QuadtreeNode node, int contador)
        {
            var children = node.children;

            //es hoja, cargar todos los meshes
            if (children == null)
            {
                selectLeafMeshes(node, contador);
            }
            //pedir hojas a hijos
            else
            {
                for (var i = 0; i < children.Length; i++)
                {
                    addAllLeafMeshes(children[i], contador);
                }
            }
        }
Ejemplo n.º 10
0
        /// <summary>
        ///     Hacer visible las meshes de un nodo si es visible por el Frustum
        /// </summary>
        private void testChildVisibility(TgcFrustum frustum, QuadtreeNode childNode,
                                         float boxLowerX, float boxLowerY, float boxLowerZ, float boxUpperX, float boxUpperY, float boxUpperZ, int contador)
        {
            //test frustum-box intersection
            var caja = new TgcBoundingAxisAlignBox(
                new Vector3(boxLowerX, boxLowerY, boxLowerZ),
                new Vector3(boxUpperX, boxUpperY, boxUpperZ));
            var c = TgcCollisionUtils.classifyFrustumAABB(frustum, caja);

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

            //parte adentro: seguir haciendo testeos con hijos
            else if (c == TgcCollisionUtils.FrustumResult.INTERSECT)
            {
                findVisibleMeshes(frustum, childNode, boxLowerX, boxLowerY, boxLowerZ, boxUpperX, boxUpperY, boxUpperZ, contador);
            }
        }
Ejemplo n.º 11
0
 private void obtenerEstadisticas(QuadtreeNode node, ref int minModels, ref int maxModels)
 {
     if (node.isLeaf())
     {
         var n = node.models.Length;
         if (n < minModels)
         {
             minModels = n;
         }
         if (n > maxModels)
         {
             maxModels = n;
         }
     }
     else
     {
         for (var i = 0; i < node.children.Length; i++)
         {
             obtenerEstadisticas(node.children[i], ref minModels, ref maxModels);
         }
     }
 }
Ejemplo n.º 12
0
        private void doCreateQuadtreeDebugBox(QuadtreeNode node, List <TgcBoxDebug> debugBoxes,
                                              float boxLowerX, float boxLowerY, float boxLowerZ,
                                              float boxUpperX, float boxUpperY, float boxUpperZ, int step)
        {
            var children = node.children;

            var midX = FastMath.Abs((boxUpperX - boxLowerX) / 2);
            var midZ = FastMath.Abs((boxUpperZ - boxLowerZ) / 2);

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

            debugBoxes.Add(box);

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

            //recursividad sobre hijos
            else
            {
                step++;

                //000
                doCreateQuadtreeDebugBox(children[0], debugBoxes, boxLowerX + midX, boxLowerY, boxLowerZ + midZ,
                                         boxUpperX, boxUpperY, boxUpperZ, step);
                //001
                doCreateQuadtreeDebugBox(children[1], debugBoxes, boxLowerX + midX, boxLowerY, boxLowerZ, boxUpperX,
                                         boxUpperY, boxUpperZ - midZ, step);

                //100
                doCreateQuadtreeDebugBox(children[2], debugBoxes, boxLowerX, boxLowerY, boxLowerZ + midZ,
                                         boxUpperX - midX, boxUpperY, boxUpperZ, step);
                //101
                doCreateQuadtreeDebugBox(children[3], debugBoxes, boxLowerX, boxLowerY, boxLowerZ, boxUpperX - midX,
                                         boxUpperY, boxUpperZ - midZ, step);
            }
        }
Ejemplo n.º 13
0
        public QuadtreeNode crearQuadtree(List <TgcMesh> TgcMeshs, TgcBoundingAxisAlignBox sceneBounds)
        {
            var rootNode = new QuadtreeNode();

            //Calcular punto medio y centro
            var midSize = sceneBounds.calculateAxisRadius();
            var center  = sceneBounds.calculateBoxCenter();

            //iniciar generacion recursiva de octree
            doSectorQuadtreeX(rootNode, center, midSize, 0, TgcMeshs);

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

            //imprimir por consola el octree
            //printDebugQuadtree(rootNode);

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

            return(rootNode);
        }
Ejemplo n.º 14
0
        /// <summary>
        ///     Recorrer recursivamente el Quadtree para encontrar los nodos visibles
        /// </summary>
        private void findVisibleMeshes(TgcFrustum frustum, QuadtreeNode node,
                                       float boxLowerX, float boxLowerY, float boxLowerZ,
                                       float boxUpperX, float boxUpperY, float boxUpperZ,
                                       int contador)
        {
            var children = node.children;

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

            //recursividad sobre hijos
            else
            {
                var midX = FastMath.Abs((boxUpperX - boxLowerX) / 2);
                var midZ = FastMath.Abs((boxUpperZ - boxLowerZ) / 2);

                //00
                testChildVisibility(frustum, children[0], boxLowerX + midX, boxLowerY, boxLowerZ + midZ, boxUpperX,
                                    boxUpperY, boxUpperZ, contador);

                //01
                testChildVisibility(frustum, children[1], boxLowerX + midX, boxLowerY, boxLowerZ, boxUpperX, boxUpperY,
                                    boxUpperZ - midZ, contador);

                //10
                testChildVisibility(frustum, children[2], boxLowerX, boxLowerY, boxLowerZ + midZ, boxUpperX - midX,
                                    boxUpperY, boxUpperZ, contador);

                //11
                testChildVisibility(frustum, children[3], boxLowerX, boxLowerY, boxLowerZ, boxUpperX - midX, boxUpperY,
                                    boxUpperZ - midZ, contador);
            }
        }
Ejemplo n.º 15
0
        /// <summary>
        ///     Corte con plano X
        /// </summary>
        private void doSectorQuadtreeX(QuadtreeNode parent, Vector3 center, Vector3 size,
                                       int step, List <TgcMesh> meshes)
        {
            var x = center.X;

            //Crear listas para realizar corte
            var possitiveList = new List <TgcMesh>();
            var negativeList  = new List <TgcMesh>();

            //X-cut
            var xCutPlane = new Plane(1, 0, 0, -x);

            splitByPlane(xCutPlane, meshes, possitiveList, negativeList);

            //recursividad de positivos con plano Z, usando resultados positivos y childIndex 0
            doSectorQuadtreeZ(parent, new Vector3(x + size.X / 2, center.Y, center.Z),
                              new Vector3(size.X / 2, size.Y, size.Z),
                              step, possitiveList, 0);

            //recursividad de negativos con plano Z, usando resultados negativos y childIndex 4
            doSectorQuadtreeZ(parent, new Vector3(x - size.X / 2, center.Y, center.Z),
                              new Vector3(size.X / 2, size.Y, size.Z),
                              step, negativeList, 2);
        }