Exemple #1
0
        public void EnforceMinimumDepth()
        {
            if (_nodeDepth < _parentTree.MinimumDepth)
            {
                if (this.HasChildren)
                {
                    _isActive = false;
                    _isSplit  = true;

                    ChildTopLeft.EnforceMinimumDepth();
                    ChildTopRight.EnforceMinimumDepth();
                    ChildBottomLeft.EnforceMinimumDepth();
                    ChildBottomRight.EnforceMinimumDepth();
                }
                else
                {
                    this.Activate();
                    _isSplit = false;
                }

                return;
            }

            if (_nodeDepth == _parentTree.MinimumDepth || (_nodeDepth < _parentTree.MinimumDepth && !this.HasChildren))
            {
                this.Activate();
                _isSplit = false;
            }
        }
Exemple #2
0
        /// <summary>
        /// Get a reference to the deepest node that contains a point.
        /// </summary>
        /// <param name="point">Vector3 representing the target point</param>
        /// <returns>Deepest quad node containing target point</returns>
        public QuadNode DeepestNodeWithPoint(Vector3 point)
        {
            //If the point isn't in this node, return null
            if (!Contains(point))
            {
                return(null);
            }

            if (HasChildren)
            {
                if (ChildTopLeft.Contains(point))
                {
                    return(ChildTopLeft.DeepestNodeWithPoint(point));
                }

                if (ChildTopRight.Contains(point))
                {
                    return(ChildTopRight.DeepestNodeWithPoint(point));
                }

                if (ChildBottomLeft.Contains(point))
                {
                    return(ChildBottomLeft.DeepestNodeWithPoint(point));
                }

                //It's contained in this node and not in the first 3
                //children, so has to be in 4th child.  No need to check.
                return(ChildBottomRight.DeepestNodeWithPoint(point));
            }

            //No children, return this QuadNode
            return(this);
        }
        /// <summary>
        /// Force the quad tree to split to the minimum depth
        /// </summary>
        internal void EnforceMinimumDepth()
        {
            if (_nodeDepth < _parentTree.MinimumDepth)
            {
                if (HasChildren)
                {
                    _isActive = false;
                    _isSplit  = true;

                    ChildTopLeft.EnforceMinimumDepth();
                    ChildTopRight.EnforceMinimumDepth();
                    ChildBottomLeft.EnforceMinimumDepth();
                    ChildBottomRight.EnforceMinimumDepth();
                }
                else
                {
                    Activate();
                    _isSplit = false;
                }

                return;
            }

            if (_nodeDepth == _parentTree.MinimumDepth)
            {
                Activate();
                _isSplit = false;
            }
        }
Exemple #4
0
        /// <summary>
        /// Add this node to the terrain's batch.
        /// </summary>
        /// <param name="fullyContained">Whether this node is known to be fully contained within the clipping frustums, in which case it and its children do not need to check clipping against it.</param>
        /// <param name="viewPoint">The position that this node is being viewed from.</param>
        /// <param name="distance">Equal to the distance from the <paramref name="viewPoint"/> to the nearest point on this node. This is needed by parent nodes for sorting, so it is calculated there and then passed down.</param>
        public void Batch(bool fullyContained, ref Vector3d viewPoint, double distance)
        {
            if (!CheckClip(ref fullyContained))
            {
                return;
            }

            double lodBlend = LodBlend(distance);

            if (lodBlend >= 1 && !IsLeaf)
            {
                TerrainTreeNode a = ChildTopLeft, b = ChildTopRight, c = ChildBottomLeft, d = ChildBottomRight;
                double          ad = ChildTopLeft.DistanceTo(ref viewPoint);
                double          bd = ChildTopRight.DistanceTo(ref viewPoint);
                double          cd = ChildBottomLeft.DistanceTo(ref viewPoint);
                double          dd = ChildBottomRight.DistanceTo(ref viewPoint);

                SortByDepth(ref ad, ref bd, ref cd, ref dd, ref a, ref b, ref c, ref d);

                a.Batch(fullyContained, ref viewPoint, ad);
                b.Batch(fullyContained, ref viewPoint, bd);
                c.Batch(fullyContained, ref viewPoint, cd);
                d.Batch(fullyContained, ref viewPoint, dd);
                return;
            }

            Terrain.AddInstanceArray(TexelCorner.X, TexelCorner.Y, Lod + lodBlend, TexelSize);
        }
Exemple #5
0
        /// <summary>
        /// Update the <see cref="Box"/> value on the basis of data read from a shader.
        /// </summary>
        /// <param name="dirty">The boundaries of the modified area in cells.</param>
        /// <param name="smallHeightData"></param>
        public void Clean(ref Box2i dirty, float[] smallHeightData)
        {
            if (dirty.Min.X > pBox.Max.X || dirty.Min.Y > pBox.Max.Z || dirty.Max.X <= pBox.Min.X || dirty.Max.Y <= pBox.Min.Z)
            {
                return;
            }

            if (IsLeaf)
            {
                var    offset = (VertexCorner.X + VertexCorner.Y * (Terrain.BlockSize / 16)) * 2;
                double min = smallHeightData[offset + 0], max = smallHeightData[offset + 1];

                pBox.Min.Y = min;
                pBox.Max.Y = max;
            }
            else
            {
                ChildTopLeft.Clean(ref dirty, smallHeightData);
                ChildTopRight.Clean(ref dirty, smallHeightData);
                ChildBottomLeft.Clean(ref dirty, smallHeightData);
                ChildBottomRight.Clean(ref dirty, smallHeightData);

                pBox.Min.Y = Math.Min(Math.Min(ChildTopLeft.pBox.Min.Y, ChildTopRight.pBox.Min.Y), Math.Min(ChildBottomLeft.pBox.Min.Y, ChildBottomRight.pBox.Min.Y));
                pBox.Max.Y = Math.Max(Math.Max(ChildTopLeft.pBox.Max.Y, ChildTopRight.pBox.Max.Y), Math.Max(ChildBottomLeft.pBox.Max.Y, ChildBottomRight.pBox.Max.Y));
            }
        }
Exemple #6
0
        internal void SetActiveVertices()
        {
            if (_parentTree.Cull && !IsInView)
            {
                return;
            }


            if (_isSplit && this.HasChildren)
            {
                ChildTopLeft.SetActiveVertices();
                ChildTopRight.SetActiveVertices();
                ChildBottomLeft.SetActiveVertices();
                ChildBottomRight.SetActiveVertices();
                return;
            }


            //Top Triangle(s)
            _parentTree.UpdateBuffer(VertexCenter.Index);
            _parentTree.UpdateBuffer(VertexTopLeft.Index);

            if (VertexTop.Activated)
            {
                _parentTree.UpdateBuffer(VertexTop.Index);

                _parentTree.UpdateBuffer(VertexCenter.Index);
                _parentTree.UpdateBuffer(VertexTop.Index);
            }
            _parentTree.UpdateBuffer(VertexTopRight.Index);

            //Right Triangle(s)
            _parentTree.UpdateBuffer(VertexCenter.Index);
            _parentTree.UpdateBuffer(VertexTopRight.Index);

            if (VertexRight.Activated)
            {
                _parentTree.UpdateBuffer(VertexRight.Index);

                _parentTree.UpdateBuffer(VertexCenter.Index);
                _parentTree.UpdateBuffer(VertexRight.Index);
            }
            _parentTree.UpdateBuffer(VertexBottomRight.Index);

            //Bottom Triangle(s)
            _parentTree.UpdateBuffer(VertexCenter.Index);
            _parentTree.UpdateBuffer(VertexBottomRight.Index);

            if (VertexBottom.Activated)
            {
                _parentTree.UpdateBuffer(VertexBottom.Index);

                _parentTree.UpdateBuffer(VertexCenter.Index);
                _parentTree.UpdateBuffer(VertexBottom.Index);
            }
            _parentTree.UpdateBuffer(VertexBottomLeft.Index);

            //Left Triangle(s)
            _parentTree.UpdateBuffer(VertexCenter.Index);
            _parentTree.UpdateBuffer(VertexBottomLeft.Index);

            if (VertexLeft.Activated)
            {
                _parentTree.UpdateBuffer(VertexLeft.Index);

                _parentTree.UpdateBuffer(VertexCenter.Index);
                _parentTree.UpdateBuffer(VertexLeft.Index);
            }
            _parentTree.UpdateBuffer(VertexTopLeft.Index);
        }
Exemple #7
0
        /// <summary>
        /// Update reference to neighboring quads
        /// </summary>
        private void AddNeighbors()
        {
            switch (NodeType)
            {
            case NodeType.TopLeft:     //Top Left Corner
                //Top neighbor
                if (_parent.NeighborTop != null)
                {
                    NeighborTop = _parent.NeighborTop.ChildBottomLeft;
                }

                //Right neighbor
                NeighborRight = _parent.ChildTopRight;
                //Bottom neighbor
                NeighborBottom = _parent.ChildBottomLeft;

                //Left neighbor
                if (_parent.NeighborLeft != null)
                {
                    NeighborLeft = _parent.NeighborLeft.ChildTopRight;
                }

                break;

            case NodeType.TopRight:     //Top Right Corner
                //Top neighbor
                if (_parent.NeighborTop != null)
                {
                    NeighborTop = _parent.NeighborTop.ChildBottomRight;
                }

                //Right neighbor
                if (_parent.NeighborRight != null)
                {
                    NeighborRight = _parent.NeighborRight.ChildTopLeft;
                }

                //Bottom neighbor
                NeighborBottom = _parent.ChildBottomRight;

                //Left neighbor
                NeighborLeft = _parent.ChildTopLeft;

                break;

            case NodeType.BottomLeft:     //Bottom Left Corner
                //Top neighbor
                NeighborTop = _parent.ChildTopLeft;

                //Right neighbor
                NeighborRight = _parent.ChildBottomRight;

                //Bottom neighbor
                if (_parent.NeighborBottom != null)
                {
                    NeighborBottom = _parent.NeighborBottom.ChildTopLeft;
                }

                //Left neighbor
                if (_parent.NeighborLeft != null)
                {
                    NeighborLeft = _parent.NeighborLeft.ChildBottomRight;
                }

                break;

            case NodeType.BottomRight:     //Bottom Right Corner
                //Top neighbor
                NeighborTop = _parent.ChildTopRight;

                //Right neighbor
                if (_parent.NeighborRight != null)
                {
                    NeighborRight = _parent.NeighborRight.ChildBottomLeft;
                }

                //Bottom neighbor
                if (_parent.NeighborBottom != null)
                {
                    NeighborBottom = _parent.NeighborBottom.ChildTopRight;
                }

                //Left neighbor
                NeighborLeft = _parent.ChildBottomLeft;

                break;
            }


            if (this.HasChildren)
            {
                ChildTopLeft.AddNeighbors();
                ChildTopRight.AddNeighbors();
                ChildBottomLeft.AddNeighbors();
                ChildBottomRight.AddNeighbors();
            }
        }
Exemple #8
0
        /// <summary>
        /// Merge split quad nodes
        /// </summary>
        public void Merge()
        {
            //Only perform the merge if there are children
            VertexTop.Activated    = false;
            VertexLeft.Activated   = false;
            VertexRight.Activated  = false;
            VertexBottom.Activated = false;

            if (NodeType != NodeType.FullNode)
            {
                VertexTopLeft.Activated     = false;
                VertexTopRight.Activated    = false;
                VertexBottomLeft.Activated  = false;
                VertexBottomRight.Activated = false;
            }
            _isActive = true;
            _isSplit  = false;

            if (HasChildren)
            {
                if (ChildTopLeft.IsSplit)
                {
                    ChildTopLeft.Merge();
                    ChildTopLeft.IsActive = false;
                }
                else
                {
                    ChildTopLeft.VertexTop.Activated    = false;
                    ChildTopLeft.VertexLeft.Activated   = false;
                    ChildTopLeft.VertexRight.Activated  = false;
                    ChildTopLeft.VertexBottom.Activated = false;
                }

                if (ChildTopRight.IsSplit)
                {
                    ChildTopRight.Merge();
                    ChildTopRight.IsActive = false;
                }
                else
                {
                    ChildTopRight.VertexTop.Activated    = false;
                    ChildTopRight.VertexLeft.Activated   = false;
                    ChildTopRight.VertexRight.Activated  = false;
                    ChildTopRight.VertexBottom.Activated = false;
                }


                if (ChildBottomLeft.IsSplit)
                {
                    ChildBottomLeft.Merge();
                    ChildBottomLeft.IsActive = false;
                }
                else
                {
                    ChildBottomLeft.VertexTop.Activated    = false;
                    ChildBottomLeft.VertexLeft.Activated   = false;
                    ChildBottomLeft.VertexRight.Activated  = false;
                    ChildBottomLeft.VertexBottom.Activated = false;
                }


                if (ChildBottomRight.IsSplit)
                {
                    ChildBottomRight.Merge();
                    ChildBottomRight.IsActive = false;
                }
                else
                {
                    ChildBottomRight.VertexTop.Activated    = false;
                    ChildBottomRight.VertexLeft.Activated   = false;
                    ChildBottomRight.VertexRight.Activated  = false;
                    ChildBottomRight.VertexBottom.Activated = false;
                }
            }
        }
Exemple #9
0
        /// <summary>
        /// Split the node by activating vertices
        /// </summary>
        public void Split()
        {
            if (_parentTree.Cull && !IsInView)
            {
                return;
            }


            //Make sure parent node is split
            if (_parent != null && !_parent.IsSplit)
            {
                _parent.Split();
            }

            if (CanSplit)
            {
                //Set active nodes
                if (HasChildren)
                {
                    ChildTopLeft.Activate();
                    ChildTopRight.Activate();
                    ChildBottomLeft.Activate();
                    ChildBottomRight.Activate();

                    _isActive = false;
                }
                else
                {
                    _isActive = true;
                }

                _isSplit = true;
                //Set active vertices
                VertexTop.Activated    = true;
                VertexLeft.Activated   = true;
                VertexRight.Activated  = true;
                VertexBottom.Activated = true;
            }

            //Make sure neighbor parents are split
            EnsureNeighborParentSplit(NeighborTop);
            EnsureNeighborParentSplit(NeighborRight);
            EnsureNeighborParentSplit(NeighborBottom);
            EnsureNeighborParentSplit(NeighborLeft);

            //Make sure neighbor vertices are active
            if (NeighborTop != null)
            {
                NeighborTop.VertexBottom.Activated = true;
            }

            if (NeighborRight != null)
            {
                NeighborRight.VertexLeft.Activated = true;
            }

            if (NeighborBottom != null)
            {
                NeighborBottom.VertexTop.Activated = true;
            }

            if (NeighborLeft != null)
            {
                NeighborLeft.VertexRight.Activated = true;
            }
        }