int split_tri_set_sorted(int[] triangles, Vector3d[] centers, int iStart, int iCount, int depth, int minTriCount, boxes_set tris, boxes_set nodes, out AxisAlignedBox3f box) { box = AxisAlignedBox3f.Empty; int iBox = -1; if (iCount < minTriCount) { // append new triangles box iBox = tris.iBoxCur++; tris.box_to_index.insert(tris.iIndicesCur, iBox); tris.index_list.insert(iCount, tris.iIndicesCur++); for (int i = 0; i < iCount; ++i) { tris.index_list.insert(triangles[iStart + i], tris.iIndicesCur++); box.Contain(mesh.GetTriBounds(triangles[iStart + i])); } tris.box_centers.insert(box.Center, iBox); tris.box_extents.insert(box.Extents, iBox); return(-(iBox + 1)); } AxisComp c = new AxisComp() { Axis = depth % 3 }; Array.Sort(centers, triangles, iStart, iCount, c); int mid = iCount / 2; int n0 = mid; int n1 = iCount - mid; // create child boxes AxisAlignedBox3f box1; int child0 = split_tri_set_sorted(triangles, centers, iStart, n0, depth + 1, minTriCount, tris, nodes, out box); int child1 = split_tri_set_sorted(triangles, centers, iStart + mid, n1, depth + 1, minTriCount, tris, nodes, out box1); box.Contain(box1); // append new box iBox = nodes.iBoxCur++; nodes.box_to_index.insert(nodes.iIndicesCur, iBox); nodes.index_list.insert(child0, nodes.iIndicesCur++); nodes.index_list.insert(child1, nodes.iIndicesCur++); nodes.box_centers.insert(box.Center, iBox); nodes.box_extents.insert(box.Extents, iBox); return(iBox); }
public static AxisAlignedBox3f Bounds <T>(IEnumerable <T> values, Func <T, Vector3f> PositionF) { AxisAlignedBox3f box = AxisAlignedBox3f.Empty; foreach (T t in values) { box.Contain(PositionF(t)); } return(box); }
public static AxisAlignedBox3f Bounds(IEnumerable <Vector3f> positions) { AxisAlignedBox3f box = AxisAlignedBox3f.Empty; foreach (Vector3f v in positions) { box.Contain(v); } return(box); }
// Appends a box that contains free triangles in one-ring of vertex vid. // If tri count is < spill threshold, push onto spill list instead. // Returns # of free tris found. int add_one_ring_box(int vid, byte[] used_triangles, int[] temp_tris, ref int iBoxCur, ref int iIndicesCur, DVector <int> spill, int nSpillThresh) { // collect free triangles int num_free = 0; foreach (int tid in mesh.VtxTrianglesItr(vid)) { if (used_triangles[tid] == 0) { temp_tris[num_free++] = tid; } } // none free, get out if (num_free == 0) { return(0); } // if we only had a couple free triangles, wait and see if // they get picked up by another vert if (num_free < nSpillThresh) { spill.Add(vid); return(num_free); } // append new box AxisAlignedBox3f box = AxisAlignedBox3f.Empty; int iBox = iBoxCur++; box_to_index.insert(iIndicesCur, iBox); index_list.insert(num_free, iIndicesCur++); for (int i = 0; i < num_free; ++i) { index_list.insert(temp_tris[i], iIndicesCur++); used_triangles[temp_tris[i]]++; // incrementing for sanity check below, just need to set to 1 box.Contain(mesh.GetTriBounds(temp_tris[i])); } box_centers.insert(box.Center, iBox); box_extents.insert(box.Extents, iBox); return(num_free); }
public AxisAlignedBox3f ToAABB() { // [TODO] probably more efficient way to do this...at minimum can move center-shift // to after the containments... Vector3f extAxis0 = Extent.x * AxisX; Vector3f extAxis1 = Extent.y * AxisY; Vector3f extAxis2 = Extent.z * AxisZ; AxisAlignedBox3f result = new AxisAlignedBox3f(Center - extAxis0 - extAxis1 - extAxis2); result.Contain(Center + extAxis0 - extAxis1 - extAxis2); result.Contain(Center + extAxis0 + extAxis1 - extAxis2); result.Contain(Center - extAxis0 + extAxis1 - extAxis2); result.Contain(Center - extAxis0 - extAxis1 + extAxis2); result.Contain(Center + extAxis0 - extAxis1 + extAxis2); result.Contain(Center + extAxis0 + extAxis1 + extAxis2); result.Contain(Center - extAxis0 + extAxis1 + extAxis2); return(result); }
int split_tri_set_midpoint(int[] triangles, Vector3d[] centers, int iStart, int iCount, int depth, int minTriCount, boxes_set tris, boxes_set nodes, out AxisAlignedBox3f box) { box = AxisAlignedBox3f.Empty; int iBox = -1; if (iCount < minTriCount) { // append new triangles box iBox = tris.iBoxCur++; tris.box_to_index.insert(tris.iIndicesCur, iBox); tris.index_list.insert(iCount, tris.iIndicesCur++); for (int i = 0; i < iCount; ++i) { tris.index_list.insert(triangles[iStart + i], tris.iIndicesCur++); box.Contain(mesh.GetTriBounds(triangles[iStart + i])); } tris.box_centers.insert(box.Center, iBox); tris.box_extents.insert(box.Extents, iBox); return(-(iBox + 1)); } //compute interval along an axis and find midpoint int axis = depth % 3; Interval1d interval = Interval1d.Empty; for (int i = 0; i < iCount; ++i) { interval.Contain(centers[iStart + i][axis]); } double midpoint = interval.Center; int n0, n1; if (Math.Abs(interval.a - interval.b) > MathUtil.ZeroTolerance) { // we have to re-sort the centers & triangles lists so that centers < midpoint // are first, so that we can recurse on the two subsets. We walk in from each side, // until we find two out-of-order locations, then we swap them. int l = 0; int r = iCount - 1; while (l < r) { // [RMS] is <= right here? if v.axis == midpoint, then this loop // can get stuck unless one of these has an equality test. But // I did not think enough about if this is the right thing to do... while (centers[iStart + l][axis] <= midpoint) { l++; } while (centers[iStart + r][axis] > midpoint) { r--; } if (l >= r) { break; //done! } //swap Vector3d tmpc = centers[iStart + l]; centers[iStart + l] = centers[iStart + r]; centers[iStart + r] = tmpc; int tmpt = triangles[iStart + l]; triangles[iStart + l] = triangles[iStart + r]; triangles[iStart + r] = tmpt; } n0 = l; n1 = iCount - n0; Debug.Assert(n0 >= 1 && n1 >= 1); } else { // interval is near-empty, so no point trying to do sorting, just split half and half n0 = iCount / 2; n1 = iCount - n0; } // create child boxes AxisAlignedBox3f box1; int child0 = split_tri_set_midpoint(triangles, centers, iStart, n0, depth + 1, minTriCount, tris, nodes, out box); int child1 = split_tri_set_midpoint(triangles, centers, iStart + n0, n1, depth + 1, minTriCount, tris, nodes, out box1); box.Contain(box1); // append new box iBox = nodes.iBoxCur++; nodes.box_to_index.insert(nodes.iIndicesCur, iBox); nodes.index_list.insert(child0, nodes.iIndicesCur++); nodes.index_list.insert(child1, nodes.iIndicesCur++); nodes.box_centers.insert(box.Center, iBox); nodes.box_extents.insert(box.Extents, iBox); return(iBox); }