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};
 }
예제 #2
0
 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;
 }