Example #1
0
        public int flattenBVHTree(BVHBuildNode node, ref int offset)
        {
            LinearBVHNode linearNode = nodes[offset];

            linearNode.bounds = node.bounds;
            int myOffset = (offset)++;

            if (node.nPrimitives > 0)
            {
                //CHECK(!node->children[0] && !node->children[1]);
                //CHECK_LT(node->nPrimitives, 65536);
                linearNode.primitivesOffset = node.firstPrimOffset;
                linearNode.nPrimitives      = node.nPrimitives;
            }
            else
            {
                // Create interior flattened BVH node
                linearNode.axis        = Convert.ToByte(node.splitAxis);
                linearNode.nPrimitives = 0;
                flattenBVHTree(node.children[0], ref offset);
                linearNode.secondChildOffset =
                    flattenBVHTree(node.children[1], ref offset);
            }
            return(myOffset);
        }
Example #2
0
 public void InitInterior(int axis, BVHBuildNode c0, BVHBuildNode c1)
 {
     children[0] = c0;
     children[1] = c1;
     bounds      = c0.bounds.Union(c1.bounds);
     splitAxis   = axis;
     nPrimitives = 0;
     //++interiorNodes;
 }
Example #3
0
        private BVHBuildNode RecursiveBuild(List <BVHPrimitiveInfo> primitiveInfo, int start, int end, ref int totalNodes, List <Primitive> orderedPrims)
        {
            //CHECK_NE(start, end);
            BVHBuildNode node = new BVHBuildNode();

            totalNodes++;
            // Compute bounds of all primitives in BVH node
            Bounds3D bounds = new Bounds3D();

            for (int i = start; i < end; ++i)
            {
                bounds = bounds.Union(primitiveInfo[i]._bounds);
            }

            int nPrimitives = end - start;

            if (nPrimitives == 1)
            {
                // Create leaf _BVHBuildNode_
                int firstPrimOffset = orderedPrims.Count;
                for (int i = start; i < end; ++i)
                {
                    int primNum = primitiveInfo[i]._primitiveNumber;
                    orderedPrims.Add(primitives[primNum]);
                }
                node.InitLeaf(firstPrimOffset, nPrimitives, bounds);
                return(node);
            }
            else
            {
                // Compute bound of primitive centroids, choose split dimension _dim_
                Bounds3D centroidBounds = new Bounds3D();
                for (int i = start; i < end; ++i)
                {
                    centroidBounds = centroidBounds.Union(primitiveInfo[i]._centroid);
                }

                int dim = centroidBounds.MaximumExtent;

                // Partition primitives into two sets and build children
                int mid = (start + end) / 2;
                if (centroidBounds.MaxPoint[dim] == centroidBounds.MinPoint[dim])
                {
                    // Create leaf _BVHBuildNode_
                    int firstPrimOffset = orderedPrims.Count;
                    for (int i = start; i < end; ++i)
                    {
                        int primNum = primitiveInfo[i]._primitiveNumber;
                        orderedPrims.Add(primitives[primNum]);
                    }
                    node.InitLeaf(firstPrimOffset, nPrimitives, bounds);
                    return(node);
                }
                else
                {
                    // Partition primitives based on _splitMethod_

                    // todo: implement me!!!
                    //switch (splitMethod)
                    //{
                    //  case SplitMethod.Middle:
                    //    {
                    //      // Partition primitives through node's midpoint
                    //      double pmid =
                    //          (centroidBounds.MinPoint[dim] + centroidBounds.MaxPoint[dim]) / 2.0;
                    //      BVHPrimitiveInfo* midPtr = std::partition(
                    //          &primitiveInfo[start], &primitiveInfo[end - 1] + 1,
                    //          [dim, pmid](const BVHPrimitiveInfo &pi) {
                    //        return pi.centroid[dim] < pmid;
                    //      });
                    //      mid = midPtr - primitiveInfo[0];
                    //      // For lots of prims with large overlapping bounding boxes, this
                    //      // may fail to partition; in that case don't break and fall
                    //      // through
                    //      // to EqualCounts.
                    //      if (mid != start && mid != end)
                    //      {
                    //        break;
                    //      }
                    //    }
                    //  case SplitMethod.EqualCounts:
                    //    {
                    //      // Partition primitives into equally-sized subsets
                    //      mid = (start + end) / 2;
                    //      std::nth_element(&primitiveInfo[start], &primitiveInfo[mid],
                    //                       &primitiveInfo[end - 1] + 1,
                    //                       [dim](const BVHPrimitiveInfo &a,
                    //                             const BVHPrimitiveInfo &b) {
                    //        return a.centroid[dim] < b.centroid[dim];
                    //      });
                    //      break;
                    //    }
                    //  case SplitMethod.SAH:
                    //  default:
                    //    {
                    //      // Partition primitives using approximate SAH
                    //      if (nPrimitives <= 2)
                    //      {
                    //        // Partition primitives into equally-sized subsets
                    //        mid = (start + end) / 2;
                    //        std::nth_element(&primitiveInfo[start], &primitiveInfo[mid],
                    //                         &primitiveInfo[end - 1] + 1,

                    //                         [dim](const BVHPrimitiveInfo &a,
                    //                                 const BVHPrimitiveInfo &b) {
                    //          return a.centroid[dim] <
                    //                 b.centroid[dim];
                    //        });
                    //      }
                    //      else
                    //      {
                    //        // Allocate _BucketInfo_ for SAH partition buckets
                    //        PBRT_CONSTEXPR int nBuckets = 12;
                    //        BucketInfo buckets[nBuckets];

                    //        // Initialize _BucketInfo_ for SAH partition buckets
                    //        for (int i = start; i < end; ++i)
                    //        {
                    //          int b = nBuckets *
                    //                  centroidBounds.Offset(
                    //                      primitiveInfo[i].centroid)[dim];
                    //          if (b == nBuckets) b = nBuckets - 1;
                    //          CHECK_GE(b, 0);
                    //          CHECK_LT(b, nBuckets);
                    //          buckets[b].count++;
                    //          buckets[b].bounds =
                    //              Union(buckets[b].bounds, primitiveInfo[i].bounds);
                    //        }

                    //        // Compute costs for splitting after each bucket
                    //        Float cost[nBuckets - 1];
                    //        for (int i = 0; i < nBuckets - 1; ++i)
                    //        {
                    //          Bounds3f b0, b1;
                    //          int count0 = 0, count1 = 0;
                    //          for (int j = 0; j <= i; ++j)
                    //          {
                    //            b0 = Union(b0, buckets[j].bounds);
                    //            count0 += buckets[j].count;
                    //          }
                    //          for (int j = i + 1; j < nBuckets; ++j)
                    //          {
                    //            b1 = Union(b1, buckets[j].bounds);
                    //            count1 += buckets[j].count;
                    //          }
                    //          cost[i] = 1 +
                    //                    (count0 * b0.SurfaceArea() +
                    //                     count1 * b1.SurfaceArea()) /
                    //                        bounds.SurfaceArea();
                    //        }

                    //        // Find bucket to split at that minimizes SAH metric
                    //        Float minCost = cost[0];
                    //        int minCostSplitBucket = 0;
                    //        for (int i = 1; i < nBuckets - 1; ++i)
                    //        {
                    //          if (cost[i] < minCost)
                    //          {
                    //            minCost = cost[i];
                    //            minCostSplitBucket = i;
                    //          }
                    //        }

                    //        // Either create leaf or split primitives at selected SAH
                    //        // bucket
                    //        Float leafCost = nPrimitives;
                    //        if (nPrimitives > maxPrimsInNode || minCost < leafCost)
                    //        {
                    //          BVHPrimitiveInfo* pmid = std::partition(
                    //              &primitiveInfo[start], &primitiveInfo[end - 1] + 1,

                    //              [=](const BVHPrimitiveInfo &pi) {
                    //            int b = nBuckets *
                    //                    centroidBounds.Offset(pi.centroid)[dim];
                    //            if (b == nBuckets) b = nBuckets - 1;
                    //            CHECK_GE(b, 0);
                    //            CHECK_LT(b, nBuckets);
                    //            return b <= minCostSplitBucket;
                    //          });
                    //          mid = pmid - &primitiveInfo[0];
                    //        }
                    //        else
                    //        {
                    //          // Create leaf _BVHBuildNode_
                    //          int firstPrimOffset = orderedPrims.size();
                    //          for (int i = start; i < end; ++i)
                    //          {
                    //            int primNum = primitiveInfo[i].primitiveNumber;
                    //            orderedPrims.push_back(primitives[primNum]);
                    //          }
                    //          node->InitLeaf(firstPrimOffset, nPrimitives, bounds);
                    //          return node;
                    //        }
                    //      }
                    //      break;
                    //    }
                    //}
                    node.InitInterior(dim,
                                      RecursiveBuild(primitiveInfo, start, mid,
                                                     ref totalNodes, orderedPrims),
                                      RecursiveBuild(primitiveInfo, mid, end,
                                                     ref totalNodes, orderedPrims));
                }
            }
            return(node);
        }