public Box3f(AxisAlignedBox3f aaBox) { Extent = 0.5f * aaBox.Diagonal; Center = aaBox.Min + Extent; AxisX = Vector3f.AxisX; AxisY = Vector3f.AxisY; AxisZ = Vector3f.AxisZ; }
public Box3f(AxisAlignedBox3f aaBox) { // [RMS] this should produce Empty for aaBox.Empty... Extent = new Vector3f(aaBox.Width * 0.5f, aaBox.Height * 0.5f, aaBox.Depth * 0.5f); Center = aaBox.Center; AxisX = Vector3f.AxisX; AxisY = Vector3f.AxisY; AxisZ = Vector3f.AxisZ; }
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); }
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); }
// 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); } } }
public AxisAlignedBox3f Intersect(AxisAlignedBox3f box) { AxisAlignedBox3f intersect = new AxisAlignedBox3f( Math.Max(Min.x, box.Min.x), Math.Max(Min.y, box.Min.y), Math.Max(Min.z, box.Min.z), Math.Min(Max.x, box.Max.x), Math.Min(Max.y, box.Max.y), Math.Min(Max.z, box.Max.z)); if (intersect.Height <= 0 || intersect.Width <= 0 || intersect.Depth <= 0) { return(AxisAlignedBox3f.Empty); } else { return(intersect); } }
// 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); }
// 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); }
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); }
public bool Intersects(AxisAlignedBox3f box) { return(!((box.Max.x <= Min.x) || (box.Min.x >= Max.x) || (box.Max.y <= Min.y) || (box.Min.y >= Max.y) || (box.Max.z <= Min.z) || (box.Min.z >= Max.z))); }
public void Contain(AxisAlignedBox3f box) { Contain(box.Min); Contain(box.Max); }