Ejemplo n.º 1
0
        // strategy here is:
        //  1) partition triangles by vertex one-rings into leaf boxes
        //      1a) first pass where we skip one-rings that have < 3 free tris
        //      1b) second pass where we handle any missed tris
        //  2) sequentially combine N leaf boxes into (N/2 + N%2) layer 2 boxes
        //  3) repeat until layer K has only 1 box, which is root of tree
        void build_by_one_rings(ClusterPolicy ePolicy)
        {
            box_to_index = new DVector <int>();
            box_centers  = new DVector <Vector3f>();
            box_extents  = new DVector <Vector3f>();
            int iBoxCur = 0;

            index_list = new DVector <int>();
            int iIndicesCur = 0;

            // replace w/ BitArray ?
            byte[] used_triangles = new byte[mesh.MaxTriangleID];
            Array.Clear(used_triangles, 0, used_triangles.Length);

            // temporary buffer
            int nMaxEdgeCount = mesh.GetMaxVtxEdgeCount();

            int[] temp_tris = new int[2 * nMaxEdgeCount];

            // first pass: cluster by one-ring, but if # of free tris
            //  in a ring is small (< 3), push onto spill list to try again,
            //  because those tris might be picked up by a bigger cluster
            DVector <int> spill = new DVector <int>();

            foreach (int vid in mesh.VertexIndices())
            {
                int tCount = add_one_ring_box(vid, used_triangles, temp_tris,
                                              ref iBoxCur, ref iIndicesCur, spill, 3);
                if (tCount < 3)
                {
                    spill.Add(vid);
                }
            }

            // second pass: check any spill vertices. Most are probably gone
            // now, but a few stray triangles might still exist
            int N = spill.Length;

            for (int si = 0; si < N; ++si)
            {
                int vid = spill[si];
                add_one_ring_box(vid, used_triangles, temp_tris,
                                 ref iBoxCur, ref iIndicesCur, null, 0);
            }


            // [RMS] test code to make sure each triangle is in exactly one list
            //foreach ( int tid in mesh.TriangleIndices() ) {
            //    int n = used_triangles[tid];
            //    if (n != 1)
            //        Util.gBreakToDebugger();
            //}

            // keep track of where triangle lists end
            triangles_end = iIndicesCur;

            // this defines ClusterPolicy.Default
            //ClusterFunctionType clusterF = cluster_boxes;
            //ClusterFunctionType clusterF = cluster_boxes_matrix;
            ClusterFunctionType clusterF = cluster_boxes_nearsearch;

            if (ePolicy == ClusterPolicy.Fastest)
            {
                clusterF = cluster_boxes;
            }
            else if (ePolicy == ClusterPolicy.MinimalVolume)
            {
                clusterF = cluster_boxes_matrix;
            }
            else if (ePolicy == ClusterPolicy.FastVolumeMetric)
            {
                clusterF = cluster_boxes_nearsearch;
            }

            // ok, now repeatedly cluster current layer of N boxes into N/2 + N%2 boxes,
            // until we hit a 1-box layer, which is root of the tree
            int nPrevEnd   = iBoxCur;
            int nLayerSize = clusterF(0, iBoxCur, ref iBoxCur, ref iIndicesCur);
            int iStart     = nPrevEnd;
            int iCount     = iBoxCur - nPrevEnd;

            while (nLayerSize > 1)
            {
                nPrevEnd   = iBoxCur;
                nLayerSize = clusterF(iStart, iCount, ref iBoxCur, ref iIndicesCur);
                iStart     = nPrevEnd;
                iCount     = iBoxCur - nPrevEnd;
            }

            root_index = iBoxCur - 1;
        }