public static OcclusionCell <T>[,] OcGrid(Vector2 size) { OcclusionCell <T>[,] grid = new OcclusionCell <T> [(int)size.x, (int)size.y]; for (int i = 0; i < size.x; i++) { for (int j = 0; j < size.y; j++) { grid[i, j].nullCell = true; } } return(grid); }
// new Intersection /// <summary> /// Calculates resultant PointValues when 2D Raster (img) is projected along Frustum at Mesh (vertices). /// Mesh represented by list of vertices. /// NOTE: projection's FOV should be full FOV angles, not half-angles. /// </summary> public List <PointValue <byte> > Intersection(Frustum projection, ref List <Vector3> vertices, ref byte[,] raster) { /// setup List <PointValue <byte> > Results = new List <PointValue <byte> >(); VerticesInView = 0; Vector2 ImgSize = new Vector2(); ImgSize.x = raster.GetLength(0); ImgSize.y = raster.GetLength(1); Vector2 OcGridSize = GridSize(projection.FOV); OcclusionCell <byte>[,] ocGrid = OcclusionCell <byte> .OcGrid(OcGridSize); /// try each vertex for (i = 0; i < vertices.Count; i++) { /// calculate position vector (world space) Vector3 Pworld = Vector(projection.Transform.position, vertices[i]); /// convert position vector (world space) to position vector (Frustum space) Vector3 Plocal = projection.Transform.InverseTransformVector(Pworld); /// convert position vector (Frustum space) to view vector (Frustum space) ViewVector Vlocal = new ViewVector(Plocal); /// check if view vector is within Frustum FOV if (Math.Abs(Vlocal.Theta) < projection.FOV.Theta / 2.0 && Math.Abs(Vlocal.Phi) < projection.FOV.Phi / 2.0) { VerticesInView++; /// map view vector to occlusion grid iOc = (int)(OcGridSize.x / 2 + OcGridSize.x * (Vlocal.Theta / projection.FOV.Theta)); jOc = (int)(OcGridSize.y / 2 + OcGridSize.y * (Vlocal.Phi / projection.FOV.Phi)); if (ocGrid[iOc, jOc].nullCell || Pworld.magnitude < ocGrid[iOc, jOc].distance) { /// map view vector to Img grid iImg = (int)(ImgSize.x / 2 + ImgSize.x * (Vlocal.Theta / projection.FOV.Theta)); jImg = (int)(ImgSize.y / 2 + ImgSize.y * (Vlocal.Phi / projection.FOV.Phi)); ocGrid[iOc, jOc].closest = vertices[i]; ocGrid[iOc, jOc].distance = Pworld.magnitude; ocGrid[iOc, jOc].value = raster[iImg, jImg]; ocGrid[iOc, jOc].nullCell = false; } } } // add vertices in occluded grid for (i = 0; i < OcGridSize.x; i++) { for (j = 0; j < OcGridSize.y; j++) { if (!ocGrid[i, j].nullCell) { Results.Add(new PointValue <byte>(ocGrid[i, j].closest, ocGrid[i, j].value)); } } } CheckedVertices = vertices.Count; NonOccludedVertices = Results.Count; return(Results); }
/* OLD INTERSECTION VERSION * /// <summary> * /// Calculates resultant PointValues when 2D Raster (img) is projected along Frustum at Mesh (vertices). * /// Mesh represented by list of vertices. * /// NOTE 1: does not currently account for occlusion. * /// NOTE 2: projection's FOV should be full FOV angles, not half-angles. * /// NOTE 3: Attempted to make generic. See note at begining of file. * /// </summary> * public List<PointValue<byte>> Intersection(Frustum projection, byte[,] img, List<Vector3> vertices) * { * /// setup * ImgPCi = img.GetLength(0); * ImgPCj = img.GetLength(1); * VerticesInView = 0; * * /// update occlusion grid * /// Cannot predeclare OcPixels because cannot add Dictionary components in declaration. * Dictionary<string, int> OcPixels = RequiredGrid(projection.FOV); * // Predeclaration of ocGrid has no benefit due to array type an dynamic size. * OcclusionCell<byte>[,] ocGrid = new OcclusionCell<byte>[OcPixels["i"], OcPixels["j"]]; * for (i = 0; i < OcPixels["i"]; i++) * { * for (j = 0; j < OcPixels["j"]; j++) * { * ocGrid[i, j].nullCell = true; * } * } * * /// try each vertex * for (i = 0; i < vertices.Count; i++) * { * /// calculate position vector (world space) * Vector(projection.Transform.position, vertices[i], ref Pworld); * * /// convert position vector (world space) to position vector (Frustum space) * Plocal = projection.Transform.InverseTransformVector(Pworld); * * /// convert position vector (Frustum space) to view vector (Frustum space) * Vlocal.Update(Plocal); * * /// check if view vector is within Frustum FOV * if (Math.Abs(Vlocal.Theta) < projection.FOV.Theta / 2.0 && * Math.Abs(Vlocal.Phi) < projection.FOV.Phi / 2.0) * { * VerticesInView++; * * /// map view vector to occlusion grid * iOc = (int)(OcPixels["i"] / 2 + OcPixels["i"] * (Vlocal.Theta / projection.FOV.Theta)); * jOc = (int)(OcPixels["j"] / 2 + OcPixels["j"] * (Vlocal.Phi / projection.FOV.Phi)); * * /// add to occlusion grid as new PointValue if not occluded * * if (ocGrid[iOc, jOc].nullCell || Pworld.magnitude < ocGrid[iOc, jOc].distance) * { * /// map view vector to img pixel grid * iImg = (int)(ImgPCi / 2 + ImgPCi * (Vlocal.Theta / projection.FOV.Theta)); * jImg = (int)(ImgPCj / 2 + ImgPCj * (Vlocal.Phi / projection.FOV.Phi)); * * /// update occlusion grid * ocGrid[iOc, jOc].pv.Update(vertices[i], img[iImg, jImg]); * ocGrid[iOc, jOc].distance = Pworld.magnitude; * ocGrid[iOc, jOc].nullCell = false; * } * } * } * * /// Alteratively could prevent reallocating using Result.Clear(), however is slow * Result = new List<PointValue<byte>>(); * for (i = 0; i < ocGrid.GetLength(0); i++) * { * for (j = 0; j < ocGrid.GetLength(1); j++) * { * if (!ocGrid[i, j].nullCell) * Result.Add(ocGrid[i, j].pv); * } * } * NonOccludedVertices = Result.Count; * return Result; * } */ // new Intersection /// <summary> /// Calculates resultant PointValues when 2D Raster (img) is projected along Frustum at Mesh (vertices). /// Mesh represented by list of vertices. /// NOTE 1: does not currently account for occlusion. /// NOTE 2: projection's FOV should be full FOV angles, not half-angles. /// NOTE 3: Attempted to make generic. See note at begining of file. /// </summary> public void Intersection(Frustum projection, List <Vector3> vertices, out List <Vector3> InView, out List <Vector3> OutView, out List <Vector3> Occluded, out List <ViewVector> VV, out List <Vector3> PVecs) { /// setup InView = new List <Vector3>(); OutView = new List <Vector3>(); Occluded = new List <Vector3>(); VV = new List <ViewVector>(); PVecs = new List <Vector3>(); // Predeclaration of ocGrid has no benefit due to array type an dynamic size. OcclusionCell <byte>[,] ocGrid = new OcclusionCell <byte> [(int)OccGridSize.x, (int)OccGridSize.y]; for (i = 0; i < OccGridSize.x; i++) { for (j = 0; j < OccGridSize.y; j++) { ocGrid[i, j].nullCell = true; ocGrid[i, j].occluded = new List <Vector3>(); } } /// try each vertex for (i = 0; i < vertices.Count; i++) { /// calculate position vector (world space) Pworld = Vector(projection.Transform.position, vertices[i]); /// convert position vector (world space) to position vector (Frustum space) Plocal = projection.Transform.InverseTransformVector(Pworld); PVecs.Add(Plocal); /// convert position vector (Frustum space) to view vector (Frustum space) ViewVector Vlocal = new ViewVector(Plocal); VV.Add(Vlocal); /// check if view vector is within Frustum FOV if (Math.Abs(Vlocal.Theta) < projection.FOV.Theta / 2.0 && Math.Abs(Vlocal.Phi) < projection.FOV.Phi / 2.0) { /// map view vector to occlusion grid iOc = (int)(OccGridSize.x / 2 + OccGridSize.x * (Vlocal.Theta / projection.FOV.Theta)); jOc = (int)(OccGridSize.y / 2 + OccGridSize.y * (Vlocal.Phi / projection.FOV.Phi)); if (ocGrid[iOc, jOc].nullCell) { ocGrid[iOc, jOc].closest = vertices[i]; ocGrid[iOc, jOc].distance = Pworld.magnitude; ocGrid[iOc, jOc].nullCell = false; } else if (Pworld.magnitude < ocGrid[iOc, jOc].distance) { ocGrid[iOc, jOc].occluded.Add(ocGrid[iOc, jOc].closest); ocGrid[iOc, jOc].closest = vertices[i]; ocGrid[iOc, jOc].distance = Pworld.magnitude; } else { ocGrid[iOc, jOc].occluded.Add(vertices[i]); } } else { OutView.Add(vertices[i]); } } // add vertices in occluded grid for (i = 0; i < OccGridSize.x; i++) { for (j = 0; j < OccGridSize.y; j++) { InView.Add(ocGrid[i, j].closest); Occluded.AddRange(ocGrid[i, j].occluded); } } InViewCount = InView.Count; OutViewCount = OutView.Count; OccludedCount = Occluded.Count; }
/// <summary> /// Calculates resultant PointValues when 2D Raster (img) is projected along Frustum at Mesh (vertices). /// Mesh represented by list of vertices. /// NOTE 1: does not currently account for occlusion. /// NOTE 2: projection's FOV should be full FOV angles, not half-angles. /// </summary> public List <PointValue <T> > Intersection <T>(Frustum projection, T[,] img, List <Vector3> vertices) { /// setup int imgPCi = img.GetLength(0); int imgPCj = img.GetLength(1); List <PointValue <T> > result = new List <PointValue <T> >(); VerticesInView = 0; /// create occlusion grid Dictionary <string, int> ocPixels = RequiredGrid(projection.FOV); int ocPCi = ocPixels["i"]; int ocPCj = ocPixels["j"]; OcclusionCell <T>[,] ocGrid = new OcclusionCell <T> [ocPCi, ocPCj]; for (int i = 0; i < ocGrid.GetLength(0); i++) { for (int j = 0; j < ocGrid.GetLength(1); j++) { ocGrid[i, j].nullCell = true; } } /// try each vertex foreach (Vector3 vertex in vertices) { /// calculate position vector (world space) Vector3 Pworld = Vector(projection.Transform.position, vertex); /// convert position vector (world space) to position vector (Frustum space) Vector3 Plocal = projection.Transform.InverseTransformVector(Pworld); /// convert position vector (Frustum space) to view vector (Frustum space) ViewVector Vlocal = new ViewVector(Plocal); /// check if view vector is within Frustum FOV if (Math.Abs(Vlocal.Theta) < projection.FOV.Theta / 2.0 && Math.Abs(Vlocal.Phi) < projection.FOV.Phi / 2.0) { VerticesInView++; /// map view vector to occlusion grid int ioc = (int)(ocPCi / 2 + ocPCi * (Vlocal.Theta / projection.FOV.Theta)); int joc = (int)(ocPCj / 2 + ocPCj * (Vlocal.Phi / projection.FOV.Phi)); /// add to occlusion grid as new PointValue if not occluded if (ocGrid[ioc, joc].nullCell || Pworld.magnitude < ocGrid[ioc, joc].distance) { /// map view vector to img pixel grid int iImg = (int)(imgPCi / 2 + imgPCi * (Vlocal.Theta / projection.FOV.Theta)); int jImg = (int)(imgPCj / 2 + imgPCj * (Vlocal.Phi / projection.FOV.Phi)); /// update occlusion grid ocGrid[ioc, joc].pv = new PointValue <T>(vertex, img[iImg, jImg]); ocGrid[ioc, joc].distance = Pworld.magnitude; ocGrid[ioc, joc].nullCell = false; } } } for (int i = 0; i < ocGrid.GetLength(0); i++) { for (int j = 0; j < ocGrid.GetLength(1); j++) { if (!ocGrid[i, j].nullCell) { result.Add(ocGrid[i, j].pv); } } } nonOccludedVertices = result.Count; return(result); }
/// <summary> /// Calculates resultant PointValues when 2D Raster (img) is projected along Frustum at Mesh (vertices). /// Mesh represented by list of vertices. /// NOTE 1: does not currently account for occlusion. /// NOTE 2: projection's FOV should be full FOV angles, not half-angles. /// NOTE 3: Attempted to make generic. See note at begining of file. /// </summary> public List <PointValue <byte> > Intersection(Frustum projection, byte[,] img, List <Vector3> vertices) { /// setup ImgPCi = img.GetLength(0); ImgPCj = img.GetLength(1); VerticesInView = 0; /// update occlusion grid /// Cannot predeclare OcPixels because cannot add Dictionary components in declaration. Dictionary <string, int> OcPixels = RequiredGrid(projection.FOV); // Predeclaration of ocGrid has no benefit due to array type an dynamic size. OcclusionCell <byte>[,] ocGrid = new OcclusionCell <byte> [OcPixels["i"], OcPixels["j"]]; for (i = 0; i < OcPixels["i"]; i++) { for (j = 0; j < OcPixels["j"]; j++) { ocGrid[i, j].nullCell = true; } } /// try each vertex for (i = 0; i < vertices.Count; i++) { /// calculate position vector (world space) Vector(projection.Transform.position, vertices[i], ref Pworld); /// convert position vector (world space) to position vector (Frustum space) Plocal = projection.Transform.InverseTransformVector(Pworld); /// convert position vector (Frustum space) to view vector (Frustum space) Vlocal.Update(Plocal); /// check if view vector is within Frustum FOV if (Math.Abs(Vlocal.Theta) < projection.FOV.Theta / 2.0 && Math.Abs(Vlocal.Phi) < projection.FOV.Phi / 2.0) { VerticesInView++; /// map view vector to occlusion grid iOc = (int)(OcPixels["i"] / 2 + OcPixels["i"] * (Vlocal.Theta / projection.FOV.Theta)); jOc = (int)(OcPixels["j"] / 2 + OcPixels["j"] * (Vlocal.Phi / projection.FOV.Phi)); /// add to occlusion grid as new PointValue if not occluded if (ocGrid[iOc, jOc].nullCell || Pworld.magnitude < ocGrid[iOc, jOc].distance) { /// map view vector to img pixel grid iImg = (int)(ImgPCi / 2 + ImgPCi * (Vlocal.Theta / projection.FOV.Theta)); jImg = (int)(ImgPCj / 2 + ImgPCj * (Vlocal.Phi / projection.FOV.Phi)); /// update occlusion grid ocGrid[iOc, jOc].pv.Update(vertices[i], img[iImg, jImg]); ocGrid[iOc, jOc].distance = Pworld.magnitude; ocGrid[iOc, jOc].nullCell = false; } } } /// Alteratively could prevent reallocating using Result.Clear(), however is slow Result = new List <PointValue <byte> >(); for (i = 0; i < ocGrid.GetLength(0); i++) { for (j = 0; j < ocGrid.GetLength(1); j++) { if (!ocGrid[i, j].nullCell) { Result.Add(ocGrid[i, j].pv); } } } NonOccludedVertices = Result.Count; return(Result); }