protected override void Execute() { PVSBounds[] bbs = m_Bounds; #if _EnabledFrumCull if (!m_IsOriCam) { List <PVSBounds> fruBounds = new List <PVSBounds>(); KdCameraInfo kdCamInfo = new KdCameraInfo(); kdCamInfo.far = m_CamInfo.far; kdCamInfo.position = m_CamInfo.position; kdCamInfo.cullMatrix = m_CamInfo.cullMatrix; var panels = kdCamInfo.CalcPanels(); for (int i = 0; i < m_Bounds.Length; ++i) { var b = m_Bounds[i]; var boundingSpere = b.boudingSpere; if (kdCamInfo.IsBoundingSphereIn(boundingSpere, panels)) { fruBounds.Add(b); } } bbs = fruBounds.ToArray(); } #endif if (bbs.Length > 0) { for (int i = m_StartIdx; i <= m_EndIdx; ++i) { Vector3 cellPt = m_CellArray[i]; CellRays(i, cellPt, bbs, m_CamInfo, m_IsOriCam); } } Dispose(); }
// 线程返回 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); } } }