Esempio n. 1
0
 public TgcPortalRenderingConnection(TgcPortalRenderingPortal portal, TgcPortalRenderingCell nextCell, TgcConvexPolygon polygon, Plane plane)
 {
     this.portal   = portal;
     this.nextCell = nextCell;
     this.polygon  = polygon;
     this.plane    = plane;
 }
 public TgcPortalRenderingConnection(TgcPortalRenderingPortal portal, TgcPortalRenderingCell nextCell, TgcConvexPolygon polygon, Plane plane)
 {
     this.portal = portal;
     this.nextCell = nextCell;
     this.polygon = polygon;
     this.plane = plane;
 }
 /// <summary>
 /// Habilitar los modelos visibles de esta celda, según el Frustum restringido
 /// </summary>
 private void findVisibleMeshes(TgcPortalRenderingCell cell, Plane[] currentFrustumPlanes)
 {
     //El Frustum puede tener más de 6 planos, asi que lo tratamos como un cuerpo convexo general.
     frustumConvexPolyhedon.Planes = currentFrustumPlanes;
     foreach (TgcMesh mesh in cell.Meshes)
     {
         if (mesh.Enabled == false)
         {
             if (TgcCollisionUtils.classifyConvexPolyhedronAABB(frustumConvexPolyhedon, mesh.BoundingBox) != TgcCollisionUtils.ConvexPolyhedronResult.OUTSIDE)
             {
                 mesh.Enabled = true;
             }
         }
     }
 }
        /// <summary>
        /// Actualiza la visibilidad de todos los modelos de las celdas.
        /// Las modelos visibles se cargan como Enable = true, mientras que el
        /// resto se deshabilita.
        /// </summary>
        /// <param name="cameraPos">Posición de la cámara</param>
        public void updateVisibility(Vector3 cameraPos)
        {
            //Armar Frustum para uso internor, en base al Frustum actual
            TgcFrustum frustum = GuiController.Instance.Frustum;

            Plane[] currentFrustumPlanes = new Plane[6];
            currentFrustumPlanes    = new Plane[6];
            currentFrustumPlanes[0] = frustum.NearPlane;
            currentFrustumPlanes[1] = frustum.FarPlane;
            currentFrustumPlanes[2] = frustum.LeftPlane;
            currentFrustumPlanes[3] = frustum.RightPlane;
            currentFrustumPlanes[4] = frustum.BottomPlane;
            currentFrustumPlanes[5] = frustum.TopPlane;

            //Deshabilitar todas las celdas
            foreach (TgcPortalRenderingCell cell in cells)
            {
                cell.Visited = false;
                foreach (TgcPortalRenderingConnection connection in cell.Connections)
                {
                    connection.Portal.Visited = false;
                }
            }

            //Buscar la celda actual en la que se encuentra la cámara
            TgcPortalRenderingCell currentCell = findCellFromPoint(cameraPos);

            if (currentCell == null)
            {
                return;
            }

            //Recorrer grafo de celdas desde la celda actual
            currentCell.Visited = true;
            traverseCellGraph(cameraPos, currentFrustumPlanes, currentCell);
        }
        /// <summary>
        /// Cargar información de PortalRendering
        /// </summary>
        public TgcPortalRenderingManager loadFromData(TgcScene scene, TgcPortalRenderingData portalRenderingData)
        {
            TgcPortalRenderingManager manager = new TgcPortalRenderingManager(scene);

            //Crear dictionary de nombres de los meshes
            Dictionary<string, TgcMesh> meshDictionary = new Dictionary<string, TgcMesh>();
            foreach (TgcMesh mesh in scene.Meshes)
            {
                meshDictionary.Add(mesh.Name, mesh);
            }

            //Cargar celdas
            foreach (TgcPortalRenderingCellData cellData in portalRenderingData.cells)
            {
                //Crear cuerpo Convexo
                TgcConvexPolyhedron convexPoly = new TgcConvexPolyhedron();
                convexPoly.Planes = new Plane[cellData.facePlanes.Length / 4];
                for (int i = 0; i < convexPoly.Planes.Length; i++)
                {
                    convexPoly.Planes[i] = new Plane(
                        cellData.facePlanes[i * 4],
                        cellData.facePlanes[i * 4 + 1],
                        cellData.facePlanes[i * 4 + 2],
                        cellData.facePlanes[i * 4 + 3]
                        );
                }
                convexPoly.BoundingVertices = new Vector3[cellData.boundingVertices.Length / 3];
                for (int i = 0; i < convexPoly.BoundingVertices.Length; i++)
                {
                    convexPoly.BoundingVertices[i] = new Vector3(
                        cellData.boundingVertices[i * 3],
                        cellData.boundingVertices[i * 3 + 1],
                        cellData.boundingVertices[i * 3 + 2]
                        );
                }

                //Crear celda
                TgcPortalRenderingCell cell = new TgcPortalRenderingCell(cellData.name, convexPoly);
                manager.Cells.Add(cell);

                //Cargar meshes en celda
                for (int i = 0; i < cellData.meshes.Length; i++)
                {
                    TgcMesh mesh = meshDictionary[cellData.meshes[i]];
                    cell.Meshes.Add(mesh);
                }
            }

            //Cargar portales
            foreach (TgcPortalRenderingPortalData portalData in portalRenderingData.portals)
            {
                //BoundingBox del portal
                TgcBoundingBox boundingBox = new TgcBoundingBox(
                    new Vector3(portalData.pMin[0], portalData.pMin[1], portalData.pMin[2]),
                    new Vector3(portalData.pMax[0], portalData.pMax[1], portalData.pMax[2])
                    );

                //Crear portal
                TgcPortalRenderingPortal portal = new TgcPortalRenderingPortal(portalData.name, boundingBox);
                manager.Portals.Add(portal);

                //Cargar conexiones para celdas A y B
                TgcPortalRenderingCell cellA = manager.Cells[portalData.cellA];
                TgcPortalRenderingCell cellB = manager.Cells[portalData.cellB];

                //Poligono del portal para la celda A
                TgcConvexPolygon polygonA = new TgcConvexPolygon();
                polygonA.BoundingVertices = new Vector3[portalData.boundingVerticesA.Length / 3];
                for (int i = 0; i < polygonA.BoundingVertices.Length; i++)
                {
                    polygonA.BoundingVertices[i] = new Vector3(
                        portalData.boundingVerticesA[i * 3],
                        portalData.boundingVerticesA[i * 3 + 1],
                        portalData.boundingVerticesA[i * 3 + 2]
                        );
                }

                //Plano del portal para la celda A
                Plane planeA = TgcParserUtils.float4ArrayToPlane(portalData.planeA);

                //Crear conexion A
                TgcPortalRenderingConnection connectionA = new TgcPortalRenderingConnection(portal, cellB, polygonA, planeA);
                cellA.Connections.Add(connectionA);

                //Poligono del portal para la celda B
                TgcConvexPolygon polygonB = new TgcConvexPolygon();
                polygonB.BoundingVertices = new Vector3[portalData.boundingVerticesB.Length / 3];
                for (int i = 0; i < polygonB.BoundingVertices.Length; i++)
                {
                    polygonB.BoundingVertices[i] = new Vector3(
                        portalData.boundingVerticesB[i * 3],
                        portalData.boundingVerticesB[i * 3 + 1],
                        portalData.boundingVerticesB[i * 3 + 2]
                        );
                }

                //Plano del portal para la celda B
                Plane planeB = TgcParserUtils.float4ArrayToPlane(portalData.planeB);

                //Crear conexion B
                TgcPortalRenderingConnection connectionB = new TgcPortalRenderingConnection(portal, cellA, polygonB, planeB);
                cellB.Connections.Add(connectionB);
            }

            return manager;
        }
        /// <summary>
        /// Recorrer el grafo de celdas y portales
        /// </summary>
        private void traverseCellGraph(Vector3 cameraPos, Plane[] currentFrustumPlanes, TgcPortalRenderingCell cell)
        {
            //Habilitar modelos visibles de esta celda
            findVisibleMeshes(cell, currentFrustumPlanes);

            //Recorrer todas la conexiones de esta celda
            foreach (TgcPortalRenderingConnection connection in cell.Connections)
            {
                //Si el portal ya fue visitado, ignorar
                //TODO: Hay una configuración extrema de celdas y portales que no es tenida en cuenta con este atajo. Analizar en más detalle.
                if (connection.Portal.Visited)
                {
                    continue;
                }

                //TODO: quizás convendria hacer un test Frustum-BoundingSphere del Portal para descartar más rápido los que no se ven

                //Hacer clipping entre el Frustum y el polígono del portal
                Vector3[] clippedPortalVerts = doPortalClipping(currentFrustumPlanes, connection.Polygon);

                //Si quedó algún remanente luego de hacer clipping, avanzar hacia esa celda
                if (clippedPortalVerts != null)
                {
                    //Crear nuevo Frustum recortado por el portal
                    Plane[] clippedFrustumPlanes = createFrustumPlanes(cameraPos, currentFrustumPlanes, clippedPortalVerts, connection.Plane);

                    //Avanzar sobre la celda que conecta este portal, utilizando el Frustum recortado
                    connection.NextCell.Visited = true;
                    connection.Portal.Visited   = true;
                    traverseCellGraph(cameraPos, clippedFrustumPlanes, connection.NextCell);
                }
            }
        }
 /// <summary>
 /// Habilitar los modelos visibles de esta celda, según el Frustum restringido
 /// </summary>
 private void findVisibleMeshes(TgcPortalRenderingCell cell, Plane[] currentFrustumPlanes)
 {
     //El Frustum puede tener más de 6 planos, asi que lo tratamos como un cuerpo convexo general.
     frustumConvexPolyhedon.Planes = currentFrustumPlanes;
     foreach (TgcMesh mesh in cell.Meshes)
     {
         if(mesh.Enabled == false)
         {
             if (TgcCollisionUtils.classifyConvexPolyhedronAABB(frustumConvexPolyhedon, mesh.BoundingBox) != TgcCollisionUtils.ConvexPolyhedronResult.OUTSIDE)
             {
                 mesh.Enabled = true;
             }
         }
     }
 }
        /// <summary>
        /// Recorrer el grafo de celdas y portales
        /// </summary>
        private void traverseCellGraph(Vector3 cameraPos, Plane[] currentFrustumPlanes, TgcPortalRenderingCell cell)
        {
            //Habilitar modelos visibles de esta celda
            findVisibleMeshes(cell, currentFrustumPlanes);

            //Recorrer todas la conexiones de esta celda
            foreach (TgcPortalRenderingConnection connection in cell.Connections)
            {
                //Si el portal ya fue visitado, ignorar
                //TODO: Hay una configuración extrema de celdas y portales que no es tenida en cuenta con este atajo. Analizar en más detalle.
                if (connection.Portal.Visited)
                    continue;

                //TODO: quizás convendria hacer un test Frustum-BoundingSphere del Portal para descartar más rápido los que no se ven

                //Hacer clipping entre el Frustum y el polígono del portal
                Vector3[] clippedPortalVerts = doPortalClipping(currentFrustumPlanes, connection.Polygon);

                //Si quedó algún remanente luego de hacer clipping, avanzar hacia esa celda
                if (clippedPortalVerts != null)
                {
                    //Crear nuevo Frustum recortado por el portal
                    Plane[] clippedFrustumPlanes = createFrustumPlanes(cameraPos, currentFrustumPlanes, clippedPortalVerts, connection.Plane);

                    //Avanzar sobre la celda que conecta este portal, utilizando el Frustum recortado
                    connection.NextCell.Visited = true;
                    connection.Portal.Visited = true;
                    traverseCellGraph(cameraPos, clippedFrustumPlanes, connection.NextCell);
                }
            }
        }
        /// <summary>
        /// Cargar información de PortalRendering
        /// </summary>
        public TgcPortalRenderingManager loadFromData(TgcScene scene, TgcPortalRenderingData portalRenderingData)
        {
            TgcPortalRenderingManager manager = new TgcPortalRenderingManager(scene);

            //Crear dictionary de nombres de los meshes
            Dictionary <string, TgcMesh> meshDictionary = new Dictionary <string, TgcMesh>();

            foreach (TgcMesh mesh in scene.Meshes)
            {
                meshDictionary.Add(mesh.Name, mesh);
            }

            //Cargar celdas
            foreach (TgcPortalRenderingCellData cellData in portalRenderingData.cells)
            {
                //Crear cuerpo Convexo
                TgcConvexPolyhedron convexPoly = new TgcConvexPolyhedron();
                convexPoly.Planes = new Plane[cellData.facePlanes.Length / 4];
                for (int i = 0; i < convexPoly.Planes.Length; i++)
                {
                    convexPoly.Planes[i] = new Plane(
                        cellData.facePlanes[i * 4],
                        cellData.facePlanes[i * 4 + 1],
                        cellData.facePlanes[i * 4 + 2],
                        cellData.facePlanes[i * 4 + 3]
                        );
                }
                convexPoly.BoundingVertices = new Vector3[cellData.boundingVertices.Length / 3];
                for (int i = 0; i < convexPoly.BoundingVertices.Length; i++)
                {
                    convexPoly.BoundingVertices[i] = new Vector3(
                        cellData.boundingVertices[i * 3],
                        cellData.boundingVertices[i * 3 + 1],
                        cellData.boundingVertices[i * 3 + 2]
                        );
                }

                //Crear celda
                TgcPortalRenderingCell cell = new TgcPortalRenderingCell(cellData.name, convexPoly);
                manager.Cells.Add(cell);

                //Cargar meshes en celda
                for (int i = 0; i < cellData.meshes.Length; i++)
                {
                    TgcMesh mesh = meshDictionary[cellData.meshes[i]];
                    cell.Meshes.Add(mesh);
                }
            }

            //Cargar portales
            foreach (TgcPortalRenderingPortalData portalData in portalRenderingData.portals)
            {
                //BoundingBox del portal
                TgcBoundingBox boundingBox = new TgcBoundingBox(
                    new Vector3(portalData.pMin[0], portalData.pMin[1], portalData.pMin[2]),
                    new Vector3(portalData.pMax[0], portalData.pMax[1], portalData.pMax[2])
                    );

                //Crear portal
                TgcPortalRenderingPortal portal = new TgcPortalRenderingPortal(portalData.name, boundingBox);
                manager.Portals.Add(portal);


                //Cargar conexiones para celdas A y B
                TgcPortalRenderingCell cellA = manager.Cells[portalData.cellA];
                TgcPortalRenderingCell cellB = manager.Cells[portalData.cellB];


                //Poligono del portal para la celda A
                TgcConvexPolygon polygonA = new TgcConvexPolygon();
                polygonA.BoundingVertices = new Vector3[portalData.boundingVerticesA.Length / 3];
                for (int i = 0; i < polygonA.BoundingVertices.Length; i++)
                {
                    polygonA.BoundingVertices[i] = new Vector3(
                        portalData.boundingVerticesA[i * 3],
                        portalData.boundingVerticesA[i * 3 + 1],
                        portalData.boundingVerticesA[i * 3 + 2]
                        );
                }

                //Plano del portal para la celda A
                Plane planeA = TgcParserUtils.float4ArrayToPlane(portalData.planeA);

                //Crear conexion A
                TgcPortalRenderingConnection connectionA = new TgcPortalRenderingConnection(portal, cellB, polygonA, planeA);
                cellA.Connections.Add(connectionA);


                //Poligono del portal para la celda B
                TgcConvexPolygon polygonB = new TgcConvexPolygon();
                polygonB.BoundingVertices = new Vector3[portalData.boundingVerticesB.Length / 3];
                for (int i = 0; i < polygonB.BoundingVertices.Length; i++)
                {
                    polygonB.BoundingVertices[i] = new Vector3(
                        portalData.boundingVerticesB[i * 3],
                        portalData.boundingVerticesB[i * 3 + 1],
                        portalData.boundingVerticesB[i * 3 + 2]
                        );
                }

                //Plano del portal para la celda B
                Plane planeB = TgcParserUtils.float4ArrayToPlane(portalData.planeB);

                //Crear conexion B
                TgcPortalRenderingConnection connectionB = new TgcPortalRenderingConnection(portal, cellA, polygonB, planeB);
                cellB.Connections.Add(connectionB);
            }

            return(manager);
        }