Example #1
0
    // List of BVHPrimitive infos including each triangle of the object
    // Start/end/total nodes for recursive split of the list
    private BVHBuildNode BuildRecursiveBVH(ref List <BVHPrimitiveInfo> primitiveInfos,
                                           int start, int end, ref int totalNodes)
    {
        BVHBuildNode node = new BVHBuildNode();

        totalNodes++;

        Bounds3 bounds = new Bounds3();

        bounds.pMin = Vector3.positiveInfinity;
        bounds.pMax = Vector3.negativeInfinity;

        // Calculate bounds of the parent BVH node from its children
        for (int i = start; i < end; i++)
        {
            bounds = bounds.Union(primitiveInfos[i].bounds);
        }

        int nPrimitives = end - start;

        // Create leaf
        if (nPrimitives == 1)
        {
            node.InitLeaf(primitiveInfos[start].triangleNo, bounds);
            return(node);
        }

        else
        {
            Bounds3 centroidBounds = new Bounds3();
            centroidBounds.pMin = Vector3.positiveInfinity;
            centroidBounds.pMax = Vector3.negativeInfinity;

            for (int i = start; i < end; i++)
            {
                centroidBounds = centroidBounds.Union(primitiveInfos[i].center);
            }
            int dim = centroidBounds.MaximumExtend();

            int mid = (start + end) / 2;

            // Order Primitives in axis 'dim' and split the list into 2 equal sized lists
            EqualCounts(ref primitiveInfos, dim, start, end);

            node.InitInterior(dim,
                              BuildRecursiveBVH(ref primitiveInfos, start, mid, ref totalNodes),
                              BuildRecursiveBVH(ref primitiveInfos, mid, end, ref totalNodes)
                              );
            return(node);
        }
    }
Example #2
0
        public PrimitiveList(IEnumerable <Primitive> primitives)
        {
            Primitives = new List <Primitive>(primitives);

            // Cache the world space bounds
            if (Primitives.Any())
            {
                worldBounds = Primitives.First().WorldBounds;
                foreach (var p in Primitives.Skip(1))
                {
                    worldBounds = worldBounds.Union(p.WorldBounds);
                }
            }
        }
Example #3
0
        public void SetTrigles(TrigleFace[] trigles)
        {
            this.trigles = trigles;
            if (trigles != null && trigles.Length > 0)
            {
                Bounds3 bounds = trigles[0].BoundBox;
                foreach (var item in trigles)
                {
                    bounds = Bounds3.Union(bounds, item.BoundBox);
                    //item.material = _material;
                }
                this.BoundBox = bounds;
            }
            else
            {
                this.BoundBox = new Bounds3();
            }

            CenterPoint = (BoundBox.pMin + BoundBox.pMax) * 0.5f;
            BVH         = BVH.Build(trigles.AsSpan());
        }
Example #4
0
File: BVH.cs Project: merwaaan/pbrt
        private BVHBuildNode RecursiveBuild(List <PrimitiveInfo> primitiveInfos, int start, int end, ref int nodeCount, ref List <Primitive> orderedPrimitives)
        {
            var node = new BVHBuildNode();

            ++nodeCount;

            // Compute the bounds of all the primitives below this node
            Bounds3 <float> bounds = new Bounds3 <float>();

            for (var i = start; i < end; ++i)
            {
                bounds = bounds.Union(primitiveInfos[i].Bounds);
            }

            var primitiveCount = end - start;

            // Create leaf node
            if (primitiveCount == 1)
            {
                var firstPrimitiveOffset = orderedPrimitives.Count();

                for (var i = start; i < end; ++i)
                {
                    orderedPrimitives.Add(allPrimitives[primitiveInfos[i].Index]);
                }

                node.InitLeaf(firstPrimitiveOffset, primitiveCount, bounds);
            }
            // Create interior node
            else
            {
                // Choose the axis to split (with the longest extent)
                var centroidBounds = new Bounds3 <float>();
                for (var i = start; i < end; ++i)
                {
                    centroidBounds = centroidBounds.Union(primitiveInfos[i].Centroid);
                }
                var dim = centroidBounds.MaximumExtent();

                var mid = (start + end) / 2;

                // Juste create a leaf node if the bounds have zero volume
                // (all centroids are at the same position)
                if (centroidBounds.Max[dim] == centroidBounds.Min[dim])
                {
                    var firstPrimitiveOffset = orderedPrimitives.Count();

                    for (var i = start; i < end; ++i)
                    {
                        orderedPrimitives.Add(allPrimitives[primitiveInfos[i].Index]);
                    }

                    node.InitLeaf(firstPrimitiveOffset, primitiveCount, bounds);
                }
                else
                {
                    // Sort primitives in the current range along the split dimension

                    var orderedRange = primitiveInfos
                                       .GetRange(start, end - start)
                                       .OrderBy(p => p.Centroid[dim]);

                    primitiveInfos = primitiveInfos.GetRange(0, start)
                                     .Concat(orderedRange)
                                     .Concat(primitiveInfos.GetRange(end, primitiveInfos.Count - end))
                                     .ToList();

                    // Recursively split the rest of the tree
                    node.InitInterior(
                        dim,
                        RecursiveBuild(primitiveInfos, start, mid, ref nodeCount, ref orderedPrimitives),
                        RecursiveBuild(primitiveInfos, mid, end, ref nodeCount, ref orderedPrimitives));
                }
            }

            return(node);
        }