long QueryRadius() { stopwatch.Reset(); stopwatch.Start(); Vector3 position = Vector3.one * 0.5f + Random.insideUnitSphere; float radius = 0.25f; results.Clear(); query.Radius(tree, position, radius, results); stopwatch.Stop(); return(stopwatch.ElapsedMilliseconds); }
// 线程返回 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); } } }
private void OnDrawGizmos() { if (query == null) { return; } Vector3 size = 0.2f * Vector3.one; for (int i = 0; i < points.Length; i++) { Gizmos.DrawCube(points[i].transform.position, size); } var resultIndices = new List <int>(); Color markColor = Color.red; markColor.a = 0.5f; Gizmos.color = markColor; switch (QueryType) { case QType.ClosestPoint: { query.ClosestPoint(tree, transform.position, resultIndices); } break; case QType.KNearest: { query.KNearest(tree, transform.position, K, resultIndices); } break; case QType.Radius: { query.Radius(tree, transform.position, Radius, 0, resultIndices); Gizmos.DrawWireSphere(transform.position, Radius); } break; case QType.Interval: { query.Interval(tree, transform.position - IntervalSize / 2f, transform.position + IntervalSize / 2f, resultIndices); Gizmos.DrawWireCube(transform.position, IntervalSize); } break; default: break; } for (int i = 0; i < resultIndices.Count; i++) { Gizmos.DrawCube(points[resultIndices[i]].transform.position, 2f * size); } Gizmos.color = Color.green; Gizmos.DrawCube(transform.position, 4f * size); if (DrawQueryNodes) { query.DrawLastQuery(); } }