public void VisualHullTest() { var view = Trafo3d.ViewTrafoRH(V3d.III, V3d.OOI, V3d.IOO); var proj = Trafo3d.PerspectiveProjectionOpenGl(-1, 1, -1, 1, 1, 100); var vpTrafo = view * proj; var frustumCorners = new Box3d(-V3d.III, V3d.III).ComputeCorners(); //Min, 0 near left bottom //new V3d(Max.X, Min.Y, Min.Z), 1 near right bottom //new V3d(Min.X, Max.Y, Min.Z), 2 near left top //new V3d(Max.X, Max.Y, Min.Z), 3 near right top //new V3d(Min.X, Min.Y, Max.Z), 4 far left bottom //new V3d(Max.X, Min.Y, Max.Z), 5 far right bottom //new V3d(Min.X, Max.Y, Max.Z), 6 far left top //Max 7 far right top // use inverse view-projection to get vertices in world space frustumCorners.Apply(c => vpTrafo.Backward.TransformPosProj(c)); // hull planes should point outside, assume right-handed transformation to build planes var refHull = new Hull3d(new[] { new Plane3d(frustumCorners[0], frustumCorners[2], frustumCorners[4]), // left new Plane3d(frustumCorners[1], frustumCorners[5], frustumCorners[3]), // right new Plane3d(frustumCorners[0], frustumCorners[4], frustumCorners[1]), // bottom new Plane3d(frustumCorners[2], frustumCorners[3], frustumCorners[6]), // top new Plane3d(frustumCorners[0], frustumCorners[1], frustumCorners[2]), // near new Plane3d(frustumCorners[4], frustumCorners[6], frustumCorners[5]), // far }); var newHull = vpTrafo.GetVisualHull(); for (int i = 0; i < 6; i++) { Report.Line("OLD: {0} NEW: {1}", newHull.PlaneArray[i], refHull.PlaneArray[i]); } // camera position should have height 1.0 from near-plane var hRef = refHull.PlaneArray[4].Height(view.GetViewPosition()); var hNew = newHull.PlaneArray[4].Height(view.GetViewPosition()); Assert.True(hRef.ApproximateEquals(1.0, 1e-7) && hRef.ApproximateEquals(hNew, 1e-7)); for (int i = 0; i < 6; i++) { Assert.True(newHull.PlaneArray[i].Coefficients.ApproxEqual(refHull.PlaneArray[i].Coefficients, 1e-7)); } }