コード例 #1
0
 public void Reset()
 {
     FreeThread();
     m_KdTree       = null;
     m_KdQuery      = null;
     m_KdTreeStatus = KdTreeStatus.None;
     if (m_KdTreeObjList != null)
     {
         m_KdTreeObjList.Clear();
     }
     if (m_TempHash != null)
     {
         m_TempHash.Clear();
     }
     if (m_LastVisibleHash != null)
     {
         m_LastVisibleHash.Clear();
     }
     if (m_ChgVisibleQueue != null)
     {
         ClearVisibleQueue(ref m_ChgVisibleQueue);
     }
     m_VisibleQueueStatus = VisibleQueueStatus.WaitQuery;
     m_KdCamInfo          = new KdCameraInfo();
     m_VisibleCount       = 0;
     m_KdTreeVisible      = 0;
 }
コード例 #2
0
    private List <Star> RegionQuery(KDTree.KDTree <Star> tree, Vector3 position, float Eps)
    {
        var pIter = tree.NearestNeighbors(new double[3] {
            position.x, position.y, position.z
        }, MinimumNeighboursAmount, Eps);

        return(pIter.ToList());
    }
コード例 #3
0
    public List <Star> GetClusteredStars(List <Star> input)
    {
        inputStarsNodes = input;
        var tree = new KDTree.KDTree <Star>(3);

        input.ForEach(p => tree.AddPoint(new double[3] {
            p.Position.x, p.Position.y, p.Position.z
        }, p));


        int clusterCounter = 0;

        foreach (var star in inputStarsNodes)
        {
            //If we already processed this star, skip it
            if (star.Visited)
            {
                continue;
            }

            star.Visited = true;

            //Todo: will the visited.false stuff be carried over?
            var neighbours = RegionQuery(tree, star.Position, Epsilon);

            //If not enough neighbours, label as noise and continue.
            if (neighbours.Count < MinimumNeighboursAmount)
            {
                star.IsNoise = true;
            }
            else
            {
                //Else, start new cluster.
                clusterCounter++;
                star.ClusterNumber = clusterCounter;

                //Expanding the new cluster
                var seedSet = neighbours;

                while (seedSet.Count > 0)
                {
                    var currentSeedPoint = seedSet[0];

                    if (currentSeedPoint.Visited == false)
                    {
                        currentSeedPoint.Visited = true;

                        var seedStarsNeighbours = RegionQuery(tree, currentSeedPoint.Position, Epsilon);
                        if (seedStarsNeighbours.Count >= MinimumNeighboursAmount)
                        {
                            seedSet.AddRange(seedStarsNeighbours);
                        }

                        if (currentSeedPoint.ClusterNumber == Star.UNASSIGNED_CLUSTER_NO)
                        {
                            currentSeedPoint.ClusterNumber = clusterCounter;
                        }
                    }

                    //Doing this to avoid infinite loop
                    seedSet.Remove(currentSeedPoint);
                }
            }
        }
        return(inputStarsNodes.Where(s => s.IsNoise == false).ToList());
    }
コード例 #4
0
    // 进入场景只Build一次,一个场景Build一次,频率还好, 内部代码有GC
    public void Build(bool isUseThread = true)
    {
        Reset();

        if (m_Clipper != null)
        {
            int cnt = m_Clipper.ObjectsCount;
            if (cnt <= 0)
            {
                return;
            }

            Action <Vector3[]> action = (Vector3[] arr) => {
                int  idx   = 0;
                bool isSet = false;

                if (m_KdTreeObjList == null)
                {
                    m_KdTreeObjList = new List <KdTreeObj>(m_Clipper.ObjectsCount);
                }
                else
                {
                    m_KdTreeObjList.Clear();
                    m_KdTreeObjList.Capacity = m_Clipper.ObjectsCount;
                }

                m_Clipper.ForEachObjects(
                    (Renderer render) =>
                {
                    Vector3 pos = render.transform.position;
                    arr[idx]    = pos;
                    ++idx;
                    isSet = true;

                    BoundingSphere boundingSpere = KdTreeCameraClipper.GetBoundingSphere(render);


                    KdTreeObj obj   = new KdTreeObj();
                    obj.InstanceId  = render.GetInstanceID();
                    obj.boundSphere = boundingSpere;
                    m_KdTreeObjList.Add(obj);
                }
                    );

                if (isSet)
                {
                    m_KdTree       = new KDTree.KDTree(arr, 32, false);
                    m_KdTreeStatus = KdTreeStatus.WaitRebuild;
                    m_UseThread    = isUseThread;

                    UpdateClipper();
                    CreateThread();
                }
            };

            if (m_VecArr == null)
            {
                m_VecArr = new Vector3[cnt];
                action(m_VecArr);
            }
            else if (cnt > m_VecArr.Length)
            {
                Array.Resize(ref m_VecArr, cnt);
                action(m_VecArr);
            }
            else
            {
                UnsafeUtil.Vector3HackArraySizeCall(m_VecArr, cnt, action);
            }
        }
    }