private static VisibleNode GetVisibleNode(int instanceId, bool isVisible) { // 内部带锁了,线程安全 VisibleNode ret = AbstractPool <VisibleNode> .GetNode() as VisibleNode; ret.InstanceId = instanceId; ret.isVisible = isVisible; return(ret); }
void ClearChgQueue() { while (m_ChgQueue != null) { var next = m_ChgQueue.NextNode; m_ChgQueue.Dispose(); m_ChgQueue = next; } }
private static void ClearVisibleQueue(ref VisibleNode root) { if (root == null) { return; } while (root != null) { VisibleNode nextNode = root.NextNode; root.Dispose(); root = nextNode; } root = null; }
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(); } } } }
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; } } } }
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; } }
// 线程返回 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); } } }