func Build(workList []BoundedVolume, minLeafItems int, leafCb LeafCallback, scoreStrategy ScoreStrategy) []scene.BvhNode {
	b := &builder{
		logger:        log.New("builder"),
		nodes:         make([]scene.BvhNode, 0),
		leafCb:        leafCb,
		minLeafItems:  minLeafItems,
		scoreChan:     make(chan splitScore, 0),
		scoreStrategy: scoreStrategy,
		stats: stats{
			totalItems: len(workList),
		},
	}
	start := time.Now()
	b.partition(workList, 0)
	b.logger.Debugf(
		"BVH tree build time: %d ms, maxDepth: %d, nodes: %d, leafs: %d\n",
		time.Since(start).Nanoseconds()/1e6,
		b.stats.maxDepth, b.stats.nodes, b.stats.leafs,
	)
	return b.nodes
}
Construct a BVH from a set of bounded volumes.

The builder uses SAH for scoring splits:
score = num_polygons * node bbox face area.

The minLeafItems param should be used to specified the minimum number of
items that can form a leaf. The BVH builder will automatically generate leafs
if the incoming work length is <= minLeafItems.
package bvh
import (
	"math"
	"time"
	"github.com/achilleasa/polaris/asset/scene"
	"github.com/achilleasa/polaris/log"
	"github.com/achilleasa/polaris/types"
)
type Axis uint8
const (
	XAxis Axis = iota
	YAxis
	ZAxis
	minSideLength float32 = 1e-3
	minSplitStep float32 = 1e-5
)
var (
	SurfaceAreaHeuristic = surfaceAreaHeuristic{}
)
type BoundedVolume interface {
	BBox() [2]types.Vec3
	Center() types.Vec3
}
type LeafCallback func(leaf *scene.BvhNode, itemList []BoundedVolume)
type ScoreStrategy interface {
	ScoreSplit(workList []BoundedVolume, splitAxis Axis, splitPoint float32) (leftCount, rightCount int, score float32)
	ScorePartition(workList []BoundedVolume) (score float32)
}
type splitScore struct {
	axis       Axis
	splitPoint float32
	leftCount, rightCount int
	score                 float32
}
type stats struct {
	partitionedItems int
	totalItems       int
	nodes            int
	leafs            int
	maxDepth         int
}
type builder struct {
	logger log.Logger
	nodes []scene.BvhNode
	leafCb LeafCallback
	minLeafItems int
	scoreChan chan splitScore
	scoreStrategy ScoreStrategy
	stats stats
}