Beispiel #1
0
        // Turn a span of N boxes into N/2 boxes, by pairing boxes
        // Except, of course, if N is odd, then we get N/2+1, where the +1
        // box has a single child box (ie just a copy).
        // [TODO] instead merge that extra box into on of parents? Reduces tree depth by 1
        int cluster_boxes(int iStart, int iCount, ref int iBoxCur, ref int iIndicesCur)
        {
            int[] indices = new int[iCount];
            for (int i = 0; i < iCount; ++i)
            {
                indices[i] = iStart + i;
            }

            int nDim = 0;

            Array.Sort(indices, (a, b) => {
                float axis_min_a = box_centers[a][nDim] - box_extents[a][nDim];
                float axis_min_b = box_centers[b][nDim] - box_extents[b][nDim];
                return((axis_min_a == axis_min_b) ? 0 :
                       (axis_min_a < axis_min_b) ? -1 : 1);
            });

            int nPairs = iCount / 2;
            int nLeft  = iCount - 2 * nPairs;

            // this is dumb! but lets us test the rest...
            for (int pi = 0; pi < nPairs; pi++)
            {
                int i0 = indices[2 * pi];
                int i1 = indices[2 * pi + 1];

                Vector3f center, extent;
                get_combined_box(i0, i1, out center, out extent);

                // append new box
                int iBox = iBoxCur++;
                box_to_index.insert(iIndicesCur, iBox);

                index_list.insert(i0 + 1, iIndicesCur++);
                index_list.insert(i1 + 1, iIndicesCur++);

                box_centers.insert(center, iBox);
                box_extents.insert(extent, iBox);
            }

            // [todo] could we merge with last other box? need a way to tell
            //   that there are 3 children though...could use negative index for that?
            if (nLeft > 0)
            {
                if (nLeft > 1)
                {
                    Util.gBreakToDebugger();
                }
                int iLeft = indices[2 * nPairs];
                duplicate_box(iLeft, ref iBoxCur, ref iIndicesCur);
            }

            return(nPairs + nLeft);
        }
Beispiel #2
0
        // accumulate triangle counts and track each box-parent index.
        // also checks that triangles are contained in boxes
        private void test_coverage(int[] tri_counts, int[] parent_indices, int iBox)
        {
            int idx = box_to_index[iBox];

            debug_check_child_tris_in_box(iBox);

            if (idx < triangles_end)
            {
                // triange-list case, array is [N t1 t2 ... tN]
                int n = index_list[idx];
                AxisAlignedBox3f box = get_box(iBox);
                for (int i = 1; i <= n; ++i)
                {
                    int ti = index_list[idx + i];
                    tri_counts[ti]++;

                    Index3i tv = mesh.GetTriangle(ti);
                    for (int j = 0; j < 3; ++j)
                    {
                        Vector3f v = (Vector3f)mesh.GetVertex(tv[j]);
                        if (!box.Contains(v))
                        {
                            Util.gBreakToDebugger();
                        }
                    }
                }
            }
            else
            {
                int i0 = index_list[idx];
                if (i0 < 0)
                {
                    // negative index means we only have one 'child' box to descend into
                    i0 = (-i0) - 1;
                    parent_indices[i0] = iBox;
                    test_coverage(tri_counts, parent_indices, i0);
                }
                else
                {
                    // positive index, two sequential child box indices to descend into
                    i0 = i0 - 1;
                    parent_indices[i0] = iBox;
                    test_coverage(tri_counts, parent_indices, i0);
                    int i1 = index_list[idx + 1];
                    i1 = i1 - 1;
                    parent_indices[i1] = iBox;
                    test_coverage(tri_counts, parent_indices, i1);
                }
            }
        }
Beispiel #3
0
        // do full tree traversal below iBox to make sure that all child points are contained
        void debug_check_child_points_in_box(int iBox)
        {
            AxisAlignedBox3d box = get_box(iBox);
            TreeTraversal    t   = new TreeTraversal()
            {
                NextPointF = (vID) => {
                    Vector3d v = points.GetVertex(vID);
                    if (box.Contains(v) == false)
                    {
                        Util.gBreakToDebugger();
                    }
                }
            };

            tree_traversal(iBox, 0, t);
        }
Beispiel #4
0
        // 1) make sure we can reach every tri in mesh through tree (also demo of how to traverse tree...)
        // 2) make sure that triangles are contained in parent boxes
        public void TestCoverage()
        {
            int[] tri_counts = new int[mesh.MaxTriangleID];
            Array.Clear(tri_counts, 0, tri_counts.Length);
            int[] parent_indices = new int[box_to_index.Length];
            Array.Clear(parent_indices, 0, parent_indices.Length);

            test_coverage(tri_counts, parent_indices, root_index);

            foreach (int ti in mesh.TriangleIndices())
            {
                if (tri_counts[ti] != 1)
                {
                    Util.gBreakToDebugger();
                }
            }
        }
Beispiel #5
0
        // 1) make sure we can reach every point through tree (also demo of how to traverse tree...)
        // 2) make sure that points are contained in parent boxes
        public void TestCoverage()
        {
            int[] point_counts = new int[points.MaxVertexID];
            Array.Clear(point_counts, 0, point_counts.Length);
            int[] parent_indices = new int[box_to_index.Length];
            Array.Clear(parent_indices, 0, parent_indices.Length);

            test_coverage(point_counts, parent_indices, root_index);

            foreach (int ti in points.VertexIndices())
            {
                if (point_counts[ti] != 1)
                {
                    Util.gBreakToDebugger();
                }
            }
        }
Beispiel #6
0
        // accumulate point counts and track each box-parent index.
        // also checks that points are contained in boxes
        private void test_coverage(int[] point_counts, int[] parent_indices, int iBox)
        {
            int idx = box_to_index[iBox];

            debug_check_child_points_in_box(iBox);

            if (idx < points_end)
            {
                // point-list case, array is [N t1 t2 ... tN]
                int n = index_list[idx];
                AxisAlignedBox3d box = get_box(iBox);
                for (int i = 1; i <= n; ++i)
                {
                    int vi = index_list[idx + i];
                    point_counts[vi]++;
                    Vector3d v = points.GetVertex(vi);
                    if (!box.Contains(v))
                    {
                        Util.gBreakToDebugger();
                    }
                }
            }
            else
            {
                int i0 = index_list[idx];
                if (i0 < 0)
                {
                    // negative index means we only have one 'child' box to descend into
                    i0 = (-i0) - 1;
                    parent_indices[i0] = iBox;
                    test_coverage(point_counts, parent_indices, i0);
                }
                else
                {
                    // positive index, two sequential child box indices to descend into
                    i0 = i0 - 1;
                    parent_indices[i0] = iBox;
                    test_coverage(point_counts, parent_indices, i0);
                    int i1 = index_list[idx + 1];
                    i1 = i1 - 1;
                    parent_indices[i1] = iBox;
                    test_coverage(point_counts, parent_indices, i1);
                }
            }
        }
Beispiel #7
0
        // do full tree traversal below iBox to make sure that all child triangles are contained
        void debug_check_child_tris_in_box(int iBox)
        {
            AxisAlignedBox3f box = get_box(iBox);
            TreeTraversal    t   = new TreeTraversal()
            {
                NextTriangleF = (tID) => {
                    Index3i tv = mesh.GetTriangle(tID);
                    for (int j = 0; j < 3; ++j)
                    {
                        Vector3f v = (Vector3f)mesh.GetVertex(tv[j]);
                        if (box.Contains(v) == false)
                        {
                            Util.gBreakToDebugger();
                        }
                    }
                }
            };

            tree_traversal(iBox, 0, t);
        }
Beispiel #8
0
        // do full tree traversal below iBox and make sure that all triangles are further
        // than box-distance-sqr
        void debug_check_child_tri_distances(int iBox, Vector3d p)
        {
            double fBoxDistSqr = box_distance_sqr(iBox, p);

            TreeTraversal t = new TreeTraversal()
            {
                NextTriangleF = (tID) => {
                    double fTriDistSqr = MeshQueries.TriDistanceSqr(mesh, tID, p);
                    if (fTriDistSqr < fBoxDistSqr)
                    {
                        if (Math.Abs(fTriDistSqr - fBoxDistSqr) > MathUtil.ZeroTolerance * 100)
                        {
                            Util.gBreakToDebugger();
                        }
                    }
                }
            };

            tree_traversal(iBox, 0, t);
        }
        protected virtual void DebugCheckVertexConstraints()
        {
            if (constraints == null)
            {
                return;
            }

            foreach (KeyValuePair <int, VertexConstraint> vc in constraints.VertexConstraintsItr())
            {
                int vid = vc.Key;
                if (vc.Value.Target != null)
                {
                    Vector3d curpos    = mesh.GetVertex(vid);
                    Vector3d projected = vc.Value.Target.Project(curpos, vid);
                    if (curpos.DistanceSquared(projected) > 0.0001f)
                    {
                        Util.gBreakToDebugger();
                    }
                }
            }
        }
Beispiel #10
0
        // do full tree traversal below iBox and make sure that all points are further
        // than box-distance-sqr
        void debug_check_child_point_distances(int iBox, Vector3d p)
        {
            double fBoxDistSqr = box_distance_sqr(iBox, ref p);

            TreeTraversal t = new TreeTraversal()
            {
                NextPointF = (vID) => {
                    Vector3d v        = points.GetVertex(vID);
                    double   fDistSqr = p.DistanceSquared(v);
                    if (fDistSqr < fBoxDistSqr)
                    {
                        if (Math.Abs(fDistSqr - fBoxDistSqr) > MathUtil.ZeroTolerance * 100)
                        {
                            Util.gBreakToDebugger();
                        }
                    }
                }
            };

            tree_traversal(iBox, 0, t);
        }
Beispiel #11
0
        // Turn a span of N boxes into N/2 boxes, by pairing boxes
        // Except, of course, if N is odd, then we get N/2+1, where the +1
        // box has a single child box (ie just a copy).
        // [TODO] instead merge that extra box into on of parents? Reduces tree depth by 1
        int cluster_boxes_nearsearch(int iStart, int iCount, ref int iBoxCur, ref int iIndicesCur)
        {
            int[] indices = new int[iCount];
            for (int i = 0; i < iCount; ++i)
            {
                indices[i] = iStart + i;
            }

            Func <int, int, double> boxMetric = combined_box_volume;
            //Func<int, int, double> boxMetric = combined_box_length;

            // sort indices by x axis
            // cycling axes (ie at each depth) seems to produce much worse results...
            int nDim = 0;

            Array.Sort(indices, (a, b) => {
                float axis_min_a = box_centers[a][nDim] - box_extents[a][nDim];
                float axis_min_b = box_centers[b][nDim] - box_extents[b][nDim];
                return((axis_min_a == axis_min_b) ? 0 :
                       (axis_min_a < axis_min_b) ? -1 : 1);
            });

            int nPairs = iCount / 2;
            int nLeft  = iCount - 2 * nPairs;

            // bounded greedy clustering.
            // Search ahead next N boxes in sorted-by-axis list, and find
            // the one that creates minimal box metric when combined with us.
            int N = BottomUpClusterLookahead;

            int[]    nextNi = new int[N];
            double[] nextNc = new double[N];
            int      pj;

            for (int pi = 0; pi < iCount - 1; pi++)
            {
                int i0 = indices[pi];
                if (i0 < 0)
                {
                    continue;
                }
                int nStop = Math.Min(N, iCount - pi - 1);
                for (int k = 0; k < nStop; ++k)
                {
                    pj        = pi + k + 1;
                    nextNi[k] = pj;
                    int ik = indices[pj];
                    if (ik < 0)
                    {
                        nextNc[k] = double.MaxValue;
                    }
                    else
                    {
                        nextNc[k] = boxMetric(i0, ik);
                    }
                }
                Array.Sort(nextNc, nextNi, 0, nStop);
                if (nextNc[0] == double.MaxValue)
                {
                    continue;
                }

                pj = nextNi[0];
                int i1 = indices[pj];
                if (i1 < 0)
                {
                    Util.gBreakToDebugger();
                }

                Vector3f center, extent;
                get_combined_box(i0, i1, out center, out extent);

                // append new box
                int iBox = iBoxCur++;
                box_to_index.insert(iIndicesCur, iBox);

                index_list.insert(i0 + 1, iIndicesCur++);
                index_list.insert(i1 + 1, iIndicesCur++);

                box_centers.insert(center, iBox);
                box_extents.insert(extent, iBox);

                indices[pi] = -(indices[pi] + 1);
                indices[pj] = -(indices[pj] + 1);
            }

            // [todo] could we merge with last other box? need a way to tell
            //   that there are 3 children though...could use negative index for that?
            if (nLeft > 0)
            {
                int iLeft = -1;
                for (int i = 0; iLeft < 0 && i < indices.Length; ++i)
                {
                    if (indices[i] >= 0)
                    {
                        iLeft = indices[i];
                    }
                }
                duplicate_box(iLeft, ref iBoxCur, ref iIndicesCur);
            }

            return(nPairs + nLeft);
        }