Пример #1
0
 /// <summary>
 /// 截头体剔除算法入口
 /// </summary>
 private void FrustumCull()
 {
     mMinQueue.Clear();
     PushBox(Tree.Root, ref Tree.Root.Box);
     while (mMinQueue.Size > 0)
     {
         OONode nd = (OONode)mMinQueue.Dequeue();
         if (mFrustum.Test(ref nd.Box) > 0)
         {
             nd.Distribute(mMaxLevel, mMaxItems);
             OOItem itm = nd.Head.Next;
             while (itm != nd.Tail)
             {
                 OOModel obj = itm.Obj;
                 if (obj.TouchId != Tree.TouchCounter)
                 {
                     obj.TouchId = Tree.TouchCounter;
                     if (mFrustum.Test(ref obj.Box) > 0)
                     {
                         obj.Next = null;
                         if (mVisible == null)
                         {
                             mVisible = mTail = obj;
                         }
                         else
                         {
                             mTail.Next = obj;
                             mTail      = obj;
                         }
                     }
                 }
                 itm = itm.Next;
             }
             if (nd.SplitAxis != OONode.LEAF)
             {
                 PushBox(nd.Left, ref nd.Left.Box);
                 PushBox(nd.Right, ref nd.Right.Box);
             }
         }
     }
 }
Пример #2
0
        /// <summary>
        /// 老旧的遮挡剔除算法入口
        /// </summary>
        private void OcclusionCullOld()
        {
            Stat[0] = Stat[1] = 0;
            Map.Clear();
            mMinQueue.Clear();
            mMaxQueue.Clear();
            PushBox(Tree.Root, ref Tree.Root.Box);
            while (mMinQueue.Size > 0)
            {
                OONode nd = (OONode)mMinQueue.Dequeue();
                nd.Distribute(mMaxLevel, mMaxItems);
                MinMax(ref nd.Box, ref nd.Box.Zmin, ref nd.Box.Zmax);
                if (nd.SplitAxis != OONode.LEAF)
                {
                    if (nd.Visible != 0 || IsVisible(1, ref nd.Box, nd.Box.Zmin) != 0)
                    {
                        nd.Visible = 1;
                        PushBox(nd.Left, ref nd.Left.Box);
                        PushBox(nd.Right, ref nd.Right.Box);
                    }
                    else
                    {
                        nd.Visible = 0;
                        if (nd.Parent != null)
                        {
                            nd.Parent.Visible = 0;
                        }
                    }
                }
                else
                {
                    if (IsVisible(1, ref nd.Box, nd.Box.Zmin) != 0)
                    {
                        OOItem itm = nd.Head.Next;
                        while (itm != nd.Tail)
                        {
                            if (itm.Obj.TouchId != Tree.TouchCounter)
                            {
                                itm.Obj.TouchId = Tree.TouchCounter;
                                OOModel obj = itm.Obj;
                                float   dis = -Vector3.Dot(obj.Box.Mid, mLook);
                                float   d   = Vector3.Dot(mAbsLook, obj.Box.Size);
                                obj.Box.Zmin = dis - d;
                                obj.Box.Zmax = dis + d;

                                if (IsVisible(0, ref obj.Box, 0) != 0)
                                {
                                    mMaxQueue.Enqueue(obj.Box.Zmax, obj, obj.Box.Zmax);
                                    obj.Next = null;
                                    if (mVisible == null)
                                    {
                                        mVisible = mTail = obj;
                                    }
                                    else
                                    {
                                        mTail.Next = obj;
                                        mTail      = obj;
                                    }
                                }
                            }
                            itm = itm.Next;
                        }
                    }
                    if (nd.Parent != null)
                    {
                        nd.Parent.Visible = 0;
                    }
                }
            }
        }
Пример #3
0
        /// <summary>
        /// 遮挡剔除 算法入口
        /// </summary>
        private void OcclusionCull()
        {
            Stat[0] = Stat[1] = 0;
            Map.Clear();
            mMinQueue.Clear();
            mMaxQueue.Clear();
            PushBox2(Tree.Root, ref Tree.Root.Box);
            // 按 负无穷范数(最小值) 作为优先权中 遍历
            while (mMinQueue.Size > 0)
            {
                OONode nd = (OONode)mMinQueue.Dequeue();
                nd.Distribute(mMaxLevel, mMaxItems);
                MinMax(ref nd.Box, ref nd.Box.Zmin, ref nd.Box.Zmax);
                if (nd.SplitAxis != OONode.LEAF) // 非叶节点
                {
                    // 该节点存在两个子节点
                    // 如果 该节点 Visible 为可见 ,则不需要进一步计算
                    // 如果 该结点 Visible 为不可见,则进一步计算判断可见性
                    // KDTree的Node不是每次重新分配,带有一定的缓存功能。所以, Visible 可以加速计算
                    // 存在一个问题:如果所有的物体都分到了一个Node中,可能会不停的划分到最大深度。后期需要优化
                    if ((nd.Visible != 0) || IsVisible(1, ref nd.Box, nd.Box.Zmin) != 0)
                    {
                        // 标记为可见
                        nd.Visible = 1;
                        // 父节点可见,接下来判断左右孩子结点的可见性
                        PushBox2(nd.Left, ref nd.Left.Box);
                        PushBox2(nd.Right, ref nd.Right.Box);
                    }
                    else
                    {
                        // 标记为不可见
                        nd.Visible = 0;
                        if (nd.Parent != null)
                        {
                            nd.Parent.Visible = 0;
                        }
                    }
                }
                else // 叶节点
                {
                    // 叶节点的Box测试
                    if (IsVisible(1, ref nd.Box, nd.Box.Zmin) != 0)
                    {
                        OOItem itm = nd.Head.Next;
                        // 保存需要绘制的物体,以 Zmax 为优先级排序
                        while (itm != nd.Tail)
                        {
                            if (itm.Obj.TouchId != Tree.TouchCounter)
                            {
                                itm.Obj.TouchId = Tree.TouchCounter;
                                OOModel obj = itm.Obj;
                                MinMax(ref obj.Box, ref obj.Box.Zmin, ref obj.Box.Zmax);
                                // 查询物体的Box是否可见
                                if (IsVisible(0, ref obj.Box, 0) != 0)
                                {
                                    // 如果一个物体的Box可见,则为待绘制的物体
                                    mMaxQueue.Enqueue(obj.Box.Zmax, obj, obj.Box.Zmax);
                                    obj.Next = null;
                                    if (mVisible == null)
                                    {
                                        mVisible = mTail = obj;
                                    }
                                    else
                                    {
                                        mTail.Next = obj;
                                        mTail      = obj;
                                    }
                                }
                            }
                            itm = itm.Next;
                        }
                    }
                    if (nd.Parent != null)
                    {
                        nd.Parent.Visible = 0;
                    }
                }
            }

#if TEST_DRAW
            VisualKDTree(Tree.Root);
            if (mMaxQueue.Size > 0)
            {
                DebugUtils.Info("OcclusionCull", "Before Max Left: ", mMaxQueue.Size);
                FlushOccluders(float.MaxValue);
                DebugUtils.Info("OcclusionCull", "After Max Left: ", mMaxQueue.Size);
            }
            Map.DrawScreenShot();
#endif
        }