private bool IsDetailedEnough(ChunkedLodTreeFactory.ChunkedLodTreeNode node)
        {
            var distanceToCamera = (node.Bounds.Center - _cameraPosition).Length;
            var screenSpaceError = (node.GeometricError / distanceToCamera) * _k;

            return screenSpaceError <= _allowedScreenSpaceError;
        }
        public void Creates_root_node_with_no_leafs_at_zero_depth()
        {
            var sut = new ChunkedLodTreeFactory();
            var expectedBounds = new Box3D(new Vector3d(-1, -2, -3), new Vector3d(1, 2, 3));

            var result = sut.Create(expectedBounds, 0);

            Assert.AreEqual(expectedBounds, result.Bounds);
            Assert.AreEqual(1, result.GeometricError);
            Assert.IsEmpty(result.Nodes);
        }
        public void Creates_root_node_with_four_children_at_depth_one()
        {
            var sut = new ChunkedLodTreeFactory();
            var expectedBounds = new Box3D(new Vector3d(-1, -1, -1), new Vector3d(1, 1, 1));

            var result = sut.Create(expectedBounds, 1);

            Assert.AreEqual(expectedBounds, result.Bounds);
            Assert.AreEqual(2, result.GeometricError);
            Assert.AreEqual(4, result.Nodes.Length);
        }
        public void Creates_children_with_correct_bounds_and_are_leafs_at_depth_one()
        {
            var sut = new ChunkedLodTreeFactory();
            var expectedBounds = new Box3D(new Vector3d(-1, -1, -1), new Vector3d(1, 1, 1));

            var result = sut.Create(expectedBounds, 1);

            AssertLeaf(new Box3D(new Vector3d(-1, -1, -1), new Vector3d(0, 0, 1)), result.Nodes[0]);
            AssertLeaf(new Box3D(new Vector3d(0, -1, -1), new Vector3d(1, 0, 1)), result.Nodes[1]);
            AssertLeaf(new Box3D(new Vector3d(-1, 0, -1), new Vector3d(0, 1, 1)), result.Nodes[2]);
            AssertLeaf(new Box3D(new Vector3d(0, 0, -1), new Vector3d(1, 1, 1)), result.Nodes[3]);
        }
        public static ChunkedLodTreeFactory.ChunkedLodTreeNode CreateTree()
        {
            var chunkedLodTreeFactory = new ChunkedLodTreeFactory();

            double width  = 8192 * 2 * 2;
            var    bounds = new Bounds2D(
                new Vector2d(-width / 2, -width / 2),
                new Vector2d(width / 2, width / 2));

            var chunkResolution = 32;
            var depth           = (int)Math.Log((width / chunkResolution), 2);

            return(chunkedLodTreeFactory.Create(bounds, depth));
        }
        public static ChunkedLodTreeFactory.ChunkedLodTreeNode CreateTree()
        {
            var chunkedLodTreeFactory = new ChunkedLodTreeFactory();

            double width = 8192 * 2 * 2;
            var bounds = new Bounds2D(
                new Vector2d(-width/2, -width/2),
                new Vector2d(width/2, width/2));

            var chunkResolution = 32;
            var depth = (int)Math.Log((width / chunkResolution), 2);

            return chunkedLodTreeFactory.Create(bounds, depth);
        }
        public void Creates_tree_for_depth_of_two()
        {
            var sut = new ChunkedLodTreeFactory();
            var expectedBounds = new Box3D(new Vector3d(-1, -1, -1), new Vector3d(1, 1, 1));

            var result = sut.Create(expectedBounds, 2);
            Assert.AreEqual(4, result.GeometricError);
            var leafs = result.Nodes.SelectMany(x => x.Nodes);

            Assert.AreEqual(16, leafs.Count());
            foreach (var leaf in leafs)
            {
                Assert.IsEmpty(leaf.Nodes);
            }
        }
        private void CalculateVisibleNodes(ChunkedLodTreeFactory.ChunkedLodTreeNode node)
        {
            if (!IsVisible(node))
                return;

            if (IsDetailedEnough(node) || node.IsLeaf())
            {
                _visibleNodes.Add(node);
                return;
            }

            foreach (var child in node.Nodes)
            {
                CalculateVisibleNodes(child);
            }
        }
        private bool IsVisible(ChunkedLodTreeFactory.ChunkedLodTreeNode node)
        {
            var center = new Vector3d(node.Bounds.Center.X, node.Bounds.Center.Y, 0);
            var delta = node.Bounds.Max - node.Bounds.Min;
            var side = Math.Max(delta.X, delta.Y);
            var radius = Math.Sqrt(side * side + side * side);

            for (var i = 0; i < _frustumPlanes.Length; i++)
            {
                var sphereIsOutsideOfPlane = PlaneDistance(_frustumPlanes[i], center) < -radius;
                if (sphereIsOutsideOfPlane)
                {
                    return false;
                }
            }

            return true;
        }
        public List<ChunkedLodTreeFactory.ChunkedLodTreeNode> Calculate(
            ChunkedLodTreeFactory.ChunkedLodTreeNode root,
            double viewportWidth,
            double horizontalFieldOfView,
            Vector3d cameraPosition,
            double allowedScreenSpaceError,
            Vector4d[] frustumPlanes)
        {
            _frustumPlanes = frustumPlanes;
            _allowedScreenSpaceError = allowedScreenSpaceError;
            _cameraPosition = cameraPosition;
            _visibleNodes = new List<ChunkedLodTreeFactory.ChunkedLodTreeNode>();
            _k = viewportWidth / (Math.Tan(horizontalFieldOfView / 2));

            CalculateVisibleNodes(root);

            return _visibleNodes;
        }
Example #11
0
        private static ChunkedLodTreeFactory.ChunkedLodTreeNode CreateTree()
        {
            var chunkedLodTreeFactory = new ChunkedLodTreeFactory();

            var bounds = new Box3D(
                new Vector3d(-4096, -4096, 0),
                new Vector3d(4096, 4096, 0));

            var levels = Math.Log((8192 / 128), 2);

            //calculate depth so that one square is one meter as maximum resolution
            return chunkedLodTreeFactory.Create(bounds, (int)8);
        }
 private void CacheNode(ChunkedLodTreeFactory.ChunkedLodTreeNode node)
 {
     _cache.Add(node);
 }
 private void AssertLeaf(Box3D expected, ChunkedLodTreeFactory.ChunkedLodTreeNode actual)
 {
     Assert.IsEmpty(actual.Nodes);
     Assert.AreEqual(1, actual.GeometricError);
     Assert.AreEqual(expected, actual.Bounds);
 }