public BinarySpacePartitionAccelerator(List<RenderItem> items, int maxdepth, int maxsize = 6) { BoundingBox bb = new BoundingBox(); Utils.CalculateBoundingBox(items, bb); double totalSurface = items.Sum(ri => ri.Surface()); root = Subdivide(maxdepth, maxsize, bb, 0x00, items, totalSurface); bb.OutParam(out x0, out x1, out y0, out y1, out z0, out z1); this.box = new double[]{x0,x1,y0,y1,z0,z1}; }
public void SplitAt(double sweep, int dim, out BoundingBox left, out BoundingBox right) { left = new BoundingBox(); left.xyz0.SetValues(this.xyz0); left.xyz1.SetValues(this.xyz1); left.xyz1[dim] = sweep; right = new BoundingBox(); right.xyz0.SetValues(this.xyz0); right.xyz1.SetValues(this.xyz1); right.xyz0[dim] = sweep; }
private static double CalculateOptimalSplit(List<RenderItem> items, int depth3, BoundingBox bb, out int maxDim, double totalSurface) { double heu, maxHeu = double.NegativeInfinity, x, maxx; maxDim = 0x00; maxx = CalculateOptimalSplit(items, bb, totalSurface, out maxHeu, depth3); x = CalculateOptimalSplit(items, bb, totalSurface, out heu, (depth3+0x01)%0x03); if(heu < maxHeu) { maxx = x; maxHeu = heu; maxDim = (depth3+0x01)%0x03; } x = CalculateOptimalSplit(items, bb, totalSurface, out heu, (depth3+0x02)%0x03); if(heu < maxHeu) { maxx = x; maxHeu = heu; maxDim = (depth3+0x02)%0x03; } return maxx; }
private static BinarySpaceNode Subdivide(int maxdepth, int maxsize, BoundingBox bb, int depth, List<RenderItem> items, double total) { if(depth >= maxdepth || items.Count <= maxsize) { return new BinarySpaceNode(items.ToArray()); } int dim; double sweep = CalculateOptimalSplit(items, depth%0x03, bb, out dim, total); BoundingBox bbleft, bbright; bb.SplitAt(sweep, dim, out bbleft, out bbright); List<RenderItem> left = new List<RenderItem>(), right = new List<RenderItem>(); double leftsf, rightsf; Split(items, dim, sweep, left, right, bbleft, bbright, out leftsf, out rightsf); return new BinarySpaceNode(Subdivide(maxdepth, maxsize, bbleft, depth+0x01, left, leftsf), Subdivide(maxdepth, maxsize, bbright, depth+0x01, right, rightsf), sweep, dim); }
private static void Split(List<RenderItem> inp, int dim, double x, List<RenderItem> left, List<RenderItem> right, BoundingBox bbl, BoundingBox bbr, out double leftsf, out double rightsf) { double x0, x1; leftsf = 0.0d; rightsf = 0.0d; foreach(RenderItem ir in inp) { ir.GetDimensionBounds(dim, out x0, out x1); if(x0 < x && (x < x1 || ir.InBox(bbl))) { left.Add(ir); leftsf += ir.Surface(); } if(x1 > x && (x > x0 || ir.InBox(bbr))) { right.Add(ir); rightsf += ir.Surface(); } } }
private static double CalculateOptimalSplit(List<RenderItem> items, BoundingBox bb, double totalSurface, out double maxHeur, int dim) { SortedSet<AddRemoveEvent> events = new SortedSet<AddRemoveEvent>(GenerateEvents(items, dim)); IEnumerator<AddRemoveEvent> aree = events.GetEnumerator(); HashSet<int> activ = new HashSet<int>(); HashSet<int> torem = new HashSet<int>(); AddRemoveEvent are; double x0, x1; int nleft = 0x00; int ntotal = items.Count; double lsf = 0.0d; bb.GetDimensionBounds(dim, out x0, out x1); maxHeur = double.PositiveInfinity; double xheu = double.NaN, heu; while(aree.MoveNext()) { are = aree.Current; double x = are.X; int index = are.Index; if(are.Add) { if(!torem.Remove(index)) { activ.Add(index); } } else { nleft++; lsf += items[index].Surface(); if(!activ.Remove(index)) { torem.Add(index); } } if(x0 < x && x < x1) { double lssf = 0.0d; foreach(int id in activ) { lssf += items[id].SplitSurface(x, dim); } heu = (nleft+activ.Count)*(lsf+lssf)+(ntotal-nleft)*(totalSurface-lsf-lssf); if(heu < maxHeur) { maxHeur = heu; xheu = x; } } } if(double.IsNaN(xheu)) { return 0.5d*(x0+x1); } return xheu; }