Ejemplo n.º 1
0
        /// <summary>
        /// This is static to make this a non-virtual call
        /// </summary>
        /// <param name="nodeData"></param>
        /// <param name="value"></param>
        private static void setVisibility(CompactQuadTree <bool> .Node nodeData, ref CullingInfo info, bool value)
        {
            // Check if visiblity has changed. This shouldnt be relevant, since only non-leaf nodes, without cullables
            //  can have this status called
            if (nodeData.Get(info.Tree) == value)
            {
                return;
            }
            nodeData.Set(info.Tree, value);


            int modifier;

            if (value)
            {
                modifier = 1;
            }
            else
            {
                modifier = -1;
            }

            var cullables = info.Culler.GetCullNode(nodeData.Index).Cullables;

            for (int i = 0; i < cullables.Count; i++)
            {
                info.CullablesReferenceCounts[cullables[i].Index] += modifier;
            }
        }
Ejemplo n.º 2
0
 public FrustumCullerView(FrustumCuller culler)
 {
     this.culler              = culler;
     visibleCullables         = new List <ICullable>();
     tree                     = new CompactQuadTree <bool>(culler.NumberLevels);
     cullablesReferenceCounts = new int[16];
 }
Ejemplo n.º 3
0
        public void TestCompactQuadTree()
        {
            var tree = new CompactQuadTree <bool>(6);

            if (tree.GetRoot().UpperLeft.UpperLeft.UpperLeft.Index != 1 + 4 + 16)
            {
                throw new Exception("Test failed");                                                                   // This is a lame test but anyways
            }
        }
Ejemplo n.º 4
0
 private void buildCullNodeArray(CullNode node, CompactQuadTree <bool> .Node cNode)
 {
     cullNodes[cNode.Index] = node;
     node.Index             = cNode.Index;
     if (QuadTree.IsLeafNode(node))
     {
         return;
     }
     buildCullNodeArray(node.NodeData.LowerLeft, cNode.LowerLeft);
     buildCullNodeArray(node.NodeData.LowerRight, cNode.LowerRight);
     buildCullNodeArray(node.NodeData.UpperLeft, cNode.UpperLeft);
     buildCullNodeArray(node.NodeData.UpperRight, cNode.UpperRight);
 }
Ejemplo n.º 5
0
        public FrustumCuller(BoundingBox quadtreeBounding, int numberLevels)
        {
            TreeBounding = quadtreeBounding;
            NumberLevels = numberLevels;
            RootNode     = new CullNode();
            QuadTreeNodeData <CullNode> data = new QuadTreeNodeData <CullNode>();

            data.BoundingBox  = quadtreeBounding;
            RootNode.NodeData = data;

            QuadTree.Split(RootNode, numberLevels - 1);

            cullNodes = new CullNode[CompactQuadTree <bool> .CalculateNbNodes(numberLevels)];
            buildCullNodeArray(RootNode, new CompactQuadTree <bool> .Node(0));

            expandCullablesBuffer();
        }
Ejemplo n.º 6
0
        /// <summary>
        /// /// This is static to make this a non-virtual call
        /// </summary>
        /// <param name="parent"></param>
        /// <param name="child"></param>
        /// <param name="frustum"></param>
        /// <param name="parentBB"></param>
        /// <param name="skipFrustumCheck"></param>
        private static void updateVisibility(CompactQuadTree <bool> .Node parent, CompactQuadTreeChild child, ref CullingInfo frustum, ref BoundingBox parentBB, bool skipFrustumCheck)
        {
            BoundingBox bb;

            switch (child)
            {
            case CompactQuadTreeChild.UpperLeft:
                bb = new BoundingBox(
                    new Vector3(
                        parentBB.Minimum.X,
                        parentBB.Minimum.Y,
                        parentBB.Minimum.Z),
                    new Vector3(
                        (parentBB.Maximum.X + parentBB.Minimum.X) * 0.5f,
                        parentBB.Maximum.Y,
                        (parentBB.Maximum.Z + parentBB.Minimum.Z) * 0.5f));
                break;

            case CompactQuadTreeChild.UpperRight:
                bb = new BoundingBox(
                    new Vector3((parentBB.Minimum.X + parentBB.Maximum.X) * 0.5f, parentBB.Minimum.Y, parentBB.Minimum.Z),
                    new Vector3(parentBB.Maximum.X, parentBB.Maximum.Y, (parentBB.Maximum.Z + parentBB.Minimum.Z) * 0.5f));
                break;

            case CompactQuadTreeChild.LowerLeft:
                bb = new BoundingBox(
                    new Vector3(parentBB.Minimum.X, parentBB.Minimum.Y, (parentBB.Maximum.Z + parentBB.Minimum.Z) * 0.5f),
                    new Vector3((parentBB.Maximum.X + parentBB.Minimum.X) * 0.5f, parentBB.Maximum.Y, parentBB.Maximum.Z));
                break;

            case CompactQuadTreeChild.LowerRight:
                bb = new BoundingBox(
                    new Vector3((parentBB.Maximum.X + parentBB.Minimum.X) * 0.5f, parentBB.Minimum.Y, (parentBB.Maximum.Z + parentBB.Minimum.Z) * 0.5f),
                    new Vector3(parentBB.Maximum.X, parentBB.Maximum.Y, parentBB.Maximum.Z));
                break;

            default:
                throw new ArgumentOutOfRangeException("child");
            }

            updateVisibility(parent.GetChild(child), ref frustum, ref bb, skipFrustumCheck);
        }
Ejemplo n.º 7
0
        private static void setInvisibleRecursive(ref CullingInfo info, ref BoundingBox bb, CompactQuadTree <bool> .Node nodeData, bool isLeaf)
        {
            if (nodeData.Get(info.Tree) == false)
            {
                return;
            }
            setVisibility(nodeData, ref info, false);

            if (isLeaf)
            {
                return;
            }
            //Note that, these calls are not strictly necessary. EDIT: are prohibited, this is exactly the speedup of using a quadtree struct
            // When traversing the tree from top to bottom, a invisible node will be reached,
            // lower nodes need not be updated.
            updateVisibility(nodeData, CompactQuadTreeChild.LowerLeft, ref info, ref bb, true);
            updateVisibility(nodeData, CompactQuadTreeChild.LowerRight, ref info, ref bb, true);
            updateVisibility(nodeData, CompactQuadTreeChild.UpperLeft, ref info, ref bb, true);
            updateVisibility(nodeData, CompactQuadTreeChild.UpperRight, ref info, ref bb, true);
        }
Ejemplo n.º 8
0
        /// <summary>
        /// This is static to make this a non-virtual call
        /// </summary>
        /// <param name="nodeData"></param>
        /// <param name="info"></param>
        /// <param name="bb"></param>
        /// <param name="skipFrustumCheck"></param>
        private static void updateVisibility(CompactQuadTree <bool> .Node nodeData, ref CullingInfo info, ref BoundingBox bb, bool skipFrustumCheck)
        {
            var isLeaf = nodeData.IsLeaf(info.Tree);

            //if (info.Culler.GetCullNode(nodeData.Index).Tag != null) System.Diagnostics.Debugger.Break();

            if (skipFrustumCheck)
            {
                if (nodeData.Get(info.Tree) == nodeData.Parent.Get(info.Tree))
                {
                    return;
                }
                setVisibility(nodeData, ref info, nodeData.Parent.Get(info.Tree));

                if (isLeaf)
                {
                    return;
                }
                updateVisibility(nodeData, CompactQuadTreeChild.LowerLeft, ref info, ref bb, true);
                updateVisibility(nodeData, CompactQuadTreeChild.LowerRight, ref info, ref bb, true);
                updateVisibility(nodeData, CompactQuadTreeChild.UpperLeft, ref info, ref bb, true);
                updateVisibility(nodeData, CompactQuadTreeChild.UpperRight, ref info, ref bb, true);

                return;
            }

            // This optimization is mainly for the pointlight shadow frustum, but probably also good for large trees
            var firstResult = info.FrustumBoundingBox.xna().Intersects(bb.xna()); // NOTE: possible slowdown due to xna() conversion

            if (!firstResult)
            {
                // The node is not in the viewing frustum, so it is surely invisible
                setInvisibleRecursive(ref info, ref bb, nodeData, isLeaf);
                return;
            }


            var result = info.Frustum.Contains(bb);

            if (result == ContainmentType.Disjoint)
            {
                setInvisibleRecursive(ref info, ref bb, nodeData, isLeaf);
                return;
            }

            if (result == ContainmentType.Contains)
            {
                if (nodeData.Get(info.Tree))
                {
                    return;
                }

                skipFrustumCheck = true;
            }

            setVisibility(nodeData, ref info, true);
            if (isLeaf)
            {
                return;
            }

            updateVisibility(nodeData, CompactQuadTreeChild.LowerLeft, ref info, ref bb, skipFrustumCheck);
            updateVisibility(nodeData, CompactQuadTreeChild.LowerRight, ref info, ref bb, skipFrustumCheck);
            updateVisibility(nodeData, CompactQuadTreeChild.UpperLeft, ref info, ref bb, skipFrustumCheck);
            updateVisibility(nodeData, CompactQuadTreeChild.UpperRight, ref info, ref bb, skipFrustumCheck);
        }