public TgcPortalRenderingCell(string name, TgcConvexPolyhedron convexPolyhedron) { this.name = name; this.convexPolyhedron = convexPolyhedron; this.meshes = new List<TgcMesh>(); this.connections = new List<TgcPortalRenderingConnection>(); }
/// <summary> /// Crear Manager /// </summary> /// <param name="scene">Escenario a administrar</param> public TgcPortalRenderingManager(TgcScene scene) { this.scene = scene; this.cells = new List<TgcPortalRenderingCell>(); this.portals = new List<TgcPortalRenderingPortal>(); this.frustumConvexPolyhedon = new TgcConvexPolyhedron(); }
/// <summary> /// Indica si un punto se encuentra dentro de un Cuerpo Convexo. /// Los planos del Cuerpo Convexo deben apuntar hacia adentro. /// Es más ágil que llamar a classifyPointConvexPolyhedron() /// </summary> /// <param name="q">Punto a clasificar</param> /// <param name="polyhedron">Cuerpo Convexo</param> /// <returns>True si se encuentra adentro.</returns> public static bool testPointConvexPolyhedron(Vector3 q, TgcConvexPolyhedron polyhedron) { for (int i = 0; i < polyhedron.Planes.Length; i++) { //Si el punto está detrás de algún plano, entonces está afuera if (TgcCollisionUtils.classifyPointPlane(q, polyhedron.Planes[i]) == PointPlaneResult.BEHIND) { return(false); } } //Si está delante de todos los planos, entonces está adentro. return(true); }
/// <summary> /// Clasifica un BoundingBox respecto de un Cuerpo Convexo. /// Los planos del Cuerpo Convexo deben apuntar hacia adentro. /// </summary> /// <param name="polyhedron">Cuerpo convexo</param> /// <param name="aabb">BoundingBox</param> /// <returns>Resultado de la clasificación</returns> public static ConvexPolyhedronResult classifyConvexPolyhedronAABB(TgcConvexPolyhedron polyhedron, TgcBoundingBox aabb) { int totalIn = 0; Plane[] polyhedronPlanes = polyhedron.Planes; // get the corners of the box into the vCorner array Vector3[] aabbCorners = aabb.computeCorners(); // test all 8 corners against the polyhedron sides // if all points are behind 1 specific plane, we are out // if we are in with all points, then we are fully in for (int p = 0; p < polyhedronPlanes.Length; ++p) { int inCount = 8; int ptIn = 1; for (int i = 0; i < 8; ++i) { // test this point against the planes if (classifyPointPlane(aabbCorners[i], polyhedronPlanes[p]) == PointPlaneResult.BEHIND) { ptIn = 0; --inCount; } } // were all the points outside of plane p? if (inCount == 0) { return(ConvexPolyhedronResult.OUTSIDE); } // check if they were all on the right side of the plane totalIn += ptIn; } // so if iTotalIn is 6, then all are inside the view if (totalIn == 6) { return(ConvexPolyhedronResult.INSIDE); } // we must be partly in then otherwise return(ConvexPolyhedronResult.INTERSECT); }
/// <summary> /// Clasifica un punto respecto de un Cuerpo Convexo de N caras. /// Puede devolver OUTSIDE o INSIDE (si es coincidente se considera como INSIDE). /// Los planos del Cuerpo Convexo deben apuntar hacia adentro. /// </summary> /// <param name="q">Punto a clasificar</param> /// <param name="polyhedron">Cuerpo Convexo</param> /// <returns>Resultado de la clasificación</returns> public static ConvexPolyhedronResult classifyPointConvexPolyhedron(Vector3 q, TgcConvexPolyhedron polyhedron) { bool fistTime = true; PointPlaneResult lastC = PointPlaneResult.BEHIND; PointPlaneResult c; for (int i = 0; i < polyhedron.Planes.Length; i++) { c = TgcCollisionUtils.classifyPointPlane(q, polyhedron.Planes[i]); if (c == PointPlaneResult.COINCIDENT) { continue; } //guardar clasif para primera vez if (fistTime) { fistTime = false; lastC = c; } //comparar con ultima clasif if (c != lastC) { //basta con que haya una distinta para que este Afuera return(ConvexPolyhedronResult.OUTSIDE); } } //Si todos dieron el mismo resultado, entonces esta adentro return(ConvexPolyhedronResult.INSIDE); }
/// <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> /// Clasifica un punto respecto de un Cuerpo Convexo de N caras. /// Puede devolver OUTSIDE o INSIDE (si es coincidente se considera como INSIDE). /// Los planos del Cuerpo Convexo deben apuntar hacia adentro. /// </summary> /// <param name="q">Punto a clasificar</param> /// <param name="polyhedron">Cuerpo Convexo</param> /// <returns>Resultado de la clasificación</returns> public static ConvexPolyhedronResult classifyPointConvexPolyhedron(Vector3 q, TgcConvexPolyhedron polyhedron) { bool fistTime = true; PointPlaneResult lastC = PointPlaneResult.BEHIND; PointPlaneResult c; for (int i = 0; i < polyhedron.Planes.Length; i++) { c = TgcCollisionUtils.classifyPointPlane(q, polyhedron.Planes[i]); if (c == PointPlaneResult.COINCIDENT) continue; //guardar clasif para primera vez if (fistTime) { fistTime = false; lastC = c; } //comparar con ultima clasif if (c != lastC) { //basta con que haya una distinta para que este Afuera return ConvexPolyhedronResult.OUTSIDE; } } //Si todos dieron el mismo resultado, entonces esta adentro return ConvexPolyhedronResult.INSIDE; }
/// <summary> /// Clasifica un BoundingBox respecto de un Cuerpo Convexo. /// Los planos del Cuerpo Convexo deben apuntar hacia adentro. /// </summary> /// <param name="polyhedron">Cuerpo convexo</param> /// <param name="aabb">BoundingBox</param> /// <returns>Resultado de la clasificación</returns> public static ConvexPolyhedronResult classifyConvexPolyhedronAABB(TgcConvexPolyhedron polyhedron, TgcBoundingBox aabb) { int totalIn = 0; Plane[] polyhedronPlanes = polyhedron.Planes; // get the corners of the box into the vCorner array Vector3[] aabbCorners = aabb.computeCorners(); // test all 8 corners against the polyhedron sides // if all points are behind 1 specific plane, we are out // if we are in with all points, then we are fully in for (int p = 0; p < polyhedronPlanes.Length; ++p) { int inCount = 8; int ptIn = 1; for (int i = 0; i < 8; ++i) { // test this point against the planes if (classifyPointPlane(aabbCorners[i], polyhedronPlanes[p]) == PointPlaneResult.BEHIND) { ptIn = 0; --inCount; } } // were all the points outside of plane p? if (inCount == 0) { return ConvexPolyhedronResult.OUTSIDE; } // check if they were all on the right side of the plane totalIn += ptIn; } // so if iTotalIn is 6, then all are inside the view if (totalIn == 6) { return ConvexPolyhedronResult.INSIDE; } // we must be partly in then otherwise return ConvexPolyhedronResult.INTERSECT; }
/// <summary> /// Indica si un punto se encuentra dentro de un Cuerpo Convexo. /// Los planos del Cuerpo Convexo deben apuntar hacia adentro. /// Es más ágil que llamar a classifyPointConvexPolyhedron() /// </summary> /// <param name="q">Punto a clasificar</param> /// <param name="polyhedron">Cuerpo Convexo</param> /// <returns>True si se encuentra adentro.</returns> public static bool testPointConvexPolyhedron(Vector3 q, TgcConvexPolyhedron polyhedron) { for (int i = 0; i < polyhedron.Planes.Length; i++) { //Si el punto está detrás de algún plano, entonces está afuera if (TgcCollisionUtils.classifyPointPlane(q, polyhedron.Planes[i]) == PointPlaneResult.BEHIND) { return false; } } //Si está delante de todos los planos, entonces está adentro. return true; }