Beispiel #1
0
    private static VisibleNode GetVisibleNode(int instanceId, bool isVisible)
    {
        // 内部带锁了,线程安全
        VisibleNode ret = AbstractPool <VisibleNode> .GetNode() as VisibleNode;

        ret.InstanceId = instanceId;
        ret.isVisible  = isVisible;
        return(ret);
    }
Beispiel #2
0
 void ClearChgQueue()
 {
     while (m_ChgQueue != null)
     {
         var next = m_ChgQueue.NextNode;
         m_ChgQueue.Dispose();
         m_ChgQueue = next;
     }
 }
Beispiel #3
0
 private static void ClearVisibleQueue(ref VisibleNode root)
 {
     if (root == null)
     {
         return;
     }
     while (root != null)
     {
         VisibleNode nextNode = root.NextNode;
         root.Dispose();
         root = nextNode;
     }
     root = null;
 }
Beispiel #4
0
    public void UptoVisibleQueue(ref VisibleNode root)
    {
        VisibleQueueStatus status = this.CurrentQueueStatus;

        if (status == VisibleQueueStatus.WaitChange)
        {
            if (m_ReadWriterLock.TryEnterWriteLock(_lockLimitMiliTime))
            {
                try {
                    m_VisibleQueueStatus = VisibleQueueStatus.WaitQuery;
                    root = m_ChgVisibleQueue;
                    m_ChgVisibleQueue = null;
                } finally {
                    m_ReadWriterLock.ExitWriteLock();
                }
            }
        }
    }
Beispiel #5
0
    void printQueue()
    {
        if (m_ChgQueue == null)
        {
            // 无数据变化
            return;
        }

        bool isNoLimit = PerMaxVisbileCount <= 0;
        int  cnt       = 0;

        while (m_ChgQueue != null)
        {
            var      next = m_ChgQueue.NextNode;
            Renderer r;
            if (!m_ObjectsMap.TryGetValue(m_ChgQueue.InstanceId, out r))
            {
                r = null;
            }
            if (r != null)
            {
                OnRenderVisibleStateChanged(r, m_ChgQueue.isVisible);
                if (AutoSetVisible)
                {
                    if (r.gameObject.activeSelf != m_ChgQueue.isVisible)
                    {
                        r.gameObject.SetActive(m_ChgQueue.isVisible);
                    }
                }
                //Debug.LogFormat ("{0} {1}", r.gameObject.name, n.isVisible? "变可见": "变非可见");
            }
            m_ChgQueue.Dispose();
            m_ChgQueue = next;

            if (!isNoLimit)
            {
                ++cnt;
                if (cnt >= PerMaxVisbileCount)
                {
                    break;
                }
            }
        }
    }
Beispiel #6
0
 private static void AddVisibleQueue(ref VisibleNode rootNode, ref VisibleNode endNode, VisibleNode visibleNode)
 {
     if (visibleNode == null)
     {
         return;
     }
     if (endNode == null)
     {
         endNode = visibleNode;
     }
     else
     {
         endNode.NextNode = visibleNode;
         endNode          = visibleNode;
     }
     if (rootNode == null)
     {
         rootNode = visibleNode;
     }
 }
Beispiel #7
0
    // 线程返回
    internal void _ThreadRun(bool doWait = true)
    {
        if (m_KdTree != null)
        {
            if (m_KdTreeStatus == KdTreeStatus.WaitRebuild)
            {
                m_KdTree.Rebuild();
                m_KdTreeStatus = KdTreeStatus.Rebuilded;

                m_ReadWriterLock.EnterWriteLock();
                m_VisibleQueueStatus = VisibleQueueStatus.WaitQuery;
                m_ReadWriterLock.ExitWriteLock();
            }
            else if (m_KdTreeStatus == KdTreeStatus.Rebuilded)
            {
                VisibleQueueStatus status = this.CurrentQueueStatus;

                if (status == VisibleQueueStatus.Refresh)
                {
                    if (m_LastVisibleHash != null)
                    {
                        m_LastVisibleHash.Clear();
                    }
                    status = VisibleQueueStatus.WaitQuery;
                }

                if (status == VisibleQueueStatus.WaitQuery)
                {
                    if (m_KdQuery == null)
                    {
                        m_KdQuery = new KDTree.KDQuery(100);
                    }
                    if (m_KdQueryIdxList == null)
                    {
                        m_KdQueryIdxList = new List <int> ();
                    }
                    else
                    {
                        m_KdQueryIdxList.Clear();
                    }

                    Vector3      center;
                    KdCameraInfo camInfo;
                    m_ReadWriterLock.EnterReadLock();
                    try {
                        camInfo = m_KdCamInfo;
                    } finally {
                        m_ReadWriterLock.ExitReadLock();
                    }
                    float radius = camInfo.far;
                    m_KdQuery.Radius(m_KdTree, camInfo.position, radius, m_KdQueryIdxList);

                    int visibleCount       = 0;
                    int kdTreeVisibleCount = m_KdQueryIdxList.Count;
                    m_TempHash.Clear();

                    if (m_KdQueryIdxList.Count > 0)
                    {
                        // 计算出摄影机面板
                                                #if _USE_WORLD_AXIS
                        KdCameraPanels camPanels = camInfo.CalcPanels();
                                                #else
                        Matrix4x4 mat       = camInfo.CalcViewProjMatrix();
                        Vector4   nearPlane = camInfo.nearPlane;
                                                #endif

                        for (int i = 0; i < m_KdQueryIdxList.Count; ++i)
                        {
                            int idx = m_KdQueryIdxList [i];
                            if (idx < 0 || idx >= m_KdTreeObjList.Count || idx >= m_VecArr.Length)
                            {
                                continue;
                            }

                            //Vector3 pos = m_VecArr [idx];
                            KdTreeObj obj = m_KdTreeObjList [idx];
                            //pos = camMVP.MultiplyPoint (pos);
                                                        #if _USE_WORLD_AXIS
                            bool isVisible = camInfo.IsBoundingSphereIn(obj.boundSphere, camPanels);
                                                        #else
                            bool isVisible = KdCameraInfo.IsBoundingSphereIn(obj.boundSphere, mat, nearPlane);                              //KdCameraInfo.NewPlane(camInfo.lookAt, camInfo.position)
                                                        #endif

                            // 摄影机剪裁
                            // 投递结果
                            if (isVisible)
                            {
                                ++visibleCount;

                                m_TempHash.Add(obj.InstanceId);
                            }
                        }
                    }

                    // 查看和上一帧变化的
                    VisibleNode chgRoot    = null;
                    VisibleNode chgEndNode = null;
                    if (m_TempHash.Count <= 0)
                    {
                        // 从有变到没有
                        if (m_LastVisibleHash != null)
                        {
                            var iter = m_LastVisibleHash.GetEnumerator();
                            while (iter.MoveNext())
                            {
                                var visibleNode = GetVisibleNode(iter.Current, false);
                                AddVisibleQueue(ref chgRoot, ref chgEndNode, visibleNode);
                            }
                            iter.Dispose();

                            m_LastVisibleHash.Clear();
                        }
                    }
                    else
                    {
                        if (m_LastVisibleHash == null)
                        {
                            m_LastVisibleHash = new HashSet <int> ();
                            var iter = m_TempHash.GetEnumerator();
                            while (iter.MoveNext())
                            {
                                var n = GetVisibleNode(iter.Current, true);
                                AddVisibleQueue(ref chgRoot, ref chgEndNode, n);
                            }
                            iter.Dispose();

                            var tmp = m_LastVisibleHash;
                            m_LastVisibleHash = m_TempHash;
                            m_TempHash        = tmp;
                        }
                        else
                        {
                            // rootNode下都是当前可见的
                            var iter = m_TempHash.GetEnumerator();
                            while (iter.MoveNext())
                            {
                                bool isContains = m_LastVisibleHash.Contains(iter.Current);
                                if (isContains)
                                {
                                    m_LastVisibleHash.Remove(iter.Current);
                                    continue;
                                }
                                var chgN = GetVisibleNode(iter.Current, true);
                                AddVisibleQueue(ref chgRoot, ref chgEndNode, chgN);
                            }
                            iter.Dispose();
                            // 剩下的就是从可见变成不可见
                            iter = m_LastVisibleHash.GetEnumerator();
                            while (iter.MoveNext())
                            {
                                var chgN = GetVisibleNode(iter.Current, false);
                                AddVisibleQueue(ref chgRoot, ref chgEndNode, chgN);
                            }
                            iter.Dispose();
                            // 交换一下
                            HashSet <int> tmp = m_LastVisibleHash;
                            m_LastVisibleHash = m_TempHash;
                            m_TempHash        = tmp;
                            m_TempHash.Clear();
                        }
                    }

                    VisibleNode tmpNode;


                    m_ReadWriterLock.EnterWriteLock();
                    try {
                        tmpNode              = m_ChgVisibleQueue;
                        m_VisibleCount       = visibleCount;
                        m_KdTreeVisible      = kdTreeVisibleCount;
                        m_ChgVisibleQueue    = chgRoot;
                        m_VisibleQueueStatus = VisibleQueueStatus.WaitChange;
                    } finally {
                        m_ReadWriterLock.ExitWriteLock();
                    }

                    if (tmpNode != null)
                    {
                        ClearVisibleQueue(ref tmpNode);
                    }
                }
                else
                {
                    doWait = false;
                }
            }

            if (doWait && _cThreadWait > 0)
            {
                System.Threading.Thread.Sleep(_cThreadWait);
            }
        }
    }