/// <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); }