func fmtSize(items ...interface{}) string {
	var totalBytes float32 = 0.0
	for _, item := range items {
		t := reflect.TypeOf(item)
		v := reflect.ValueOf(item)
		if v.Len() == 0 {
			continue
		}
		totalBytes += float32(int(t.Elem().Size()) * v.Len())
	}
	if totalBytes < 1e3 {
		return fmt.Sprintf("%3d bytes", int(totalBytes))
	} else if totalBytes < 1e6 {
		return fmt.Sprintf("%3.1f kb", totalBytes/1e3)
	}
	return fmt.Sprintf("%5.1f mb", totalBytes/1e6)
}
Sum the total space used by a set of slices and return back a formatted
value with the appropriate byte/kb/mb unit.
package scene
import (
	"bytes"
	"fmt"
	"reflect"
	"strings"
	"github.com/achilleasa/polaris/asset/texure"
	"github.com/achilleasa/polaris/types"
	"github.com/olekukonko/tablewriter"
)
type BvhNode struct {
	Min   types.Vec3
	LData int32
	Max   types.Vec3
	RData int32
}
func (n *BvhNode) SetBBox(bbox [2]types.Vec3) {
	n.Min = bbox[0]
	n.Max = bbox[1]
}
func (n *BvhNode) SetChildNodes(left, right uint32) {
	n.LData = int32(left)
	n.RData = int32(right)
}
func (n *BvhNode) SetMeshIndex(index uint32) {
	n.LData = -int32(index)
}
func (n *BvhNode) GetMeshIndex() (index uint32) {
	return uint32(-n.LData)
}
func (n *BvhNode) SetPrimitives(firstPrimIndex, count uint32) {
	n.LData = -int32(firstPrimIndex)
	n.RData = int32(count)
}
func (n *BvhNode) GetPrimitives() (firstPrimIndex, count uint32) {
	return uint32(-n.LData), uint32(n.RData)
}
func (n *BvhNode) OffsetChildNodes(offset int32) {
	if n.LData <= 0 {
		return
	}
	n.LData += offset
	n.RData += offset
}
type MaterialNode struct {
	Union1 [4]int32
	Union2 types.Vec4
	Union3 types.Vec4
	Union4 types.Vec3
	Union5 [1]int32
}
type EmissivePrimitiveType uint32
const (
	AreaLight EmissivePrimitiveType = iota
	EnvironmentLight
)
type EmissivePrimitive struct {
	Transform types.Mat4
	Area float32
	PrimitiveIndex uint32
	MaterialNodeIndex uint32
	Type EmissivePrimitiveType
}
type MeshInstance struct {
	MeshIndex uint32
	BvhRoot uint32
	padding [2]uint32
	Transform types.Mat4
}
type TextureMetadata struct {
	Format texture.Format
	Width  uint32
	Height uint32
	DataOffset uint32
}
type Scene struct {
	BvhNodeList        []BvhNode
	MeshInstanceList   []MeshInstance
	MaterialNodeList   []MaterialNode
	EmissivePrimitives []EmissivePrimitive
	TextureData     []byte
	TextureMetadata []TextureMetadata
	VertexList    []types.Vec4
	NormalList    []types.Vec4
	UvList        []types.Vec2
	MaterialIndex []uint32
	SceneDiffuseMatIndex  int32
	SceneEmissiveMatIndex int32
	Camera *Camera
}
func (sc *Scene) Stats() string {
	var buf bytes.Buffer
	table := tablewriter.NewWriter(&buf)
	table.SetAlignment(tablewriter.ALIGN_LEFT)
	table.SetAutoFormatHeaders(false)
	table.SetHeader([]string{"Asset Type", "Asset", "Size"})
	table.Append([]string{"Geometry", "---", fmtSize(sc.VertexList, sc.NormalList, sc.UvList, sc.BvhNodeList)})
	table.Append([]string{"", "Vertices", fmtSize(sc.VertexList)})
	table.Append([]string{"", "Normals", fmtSize(sc.NormalList)})
	table.Append([]string{"", "UVs", fmtSize(sc.UvList)})
	table.Append([]string{"", "BVH", fmtSize(sc.BvhNodeList)})
	table.Append([]string{" ", " ", " "})
	table.Append([]string{"Mesh/emissives", "---", fmtSize(sc.MeshInstanceList, sc.EmissivePrimitives)})
	table.Append([]string{"", "Mesh instances", fmtSize(sc.MeshInstanceList)})
	table.Append([]string{"", "Emissives", fmtSize(sc.EmissivePrimitives)})
	table.Append([]string{" ", " ", " "})
	table.Append([]string{"Materials", "---", fmtSize(sc.MaterialIndex, sc.MaterialNodeList)})
	table.Append([]string{"", "Mat. indices", fmtSize(sc.MaterialIndex)})
	table.Append([]string{"", "Mat. nodes", fmtSize(sc.MaterialNodeList)})
	table.Append([]string{" ", " ", " "})
	table.Append([]string{"Textures", "---", fmtSize(sc.TextureMetadata, sc.TextureData)})
	table.Append([]string{"", "Metadata", fmtSize(sc.TextureMetadata)})
	table.Append([]string{"", "Data", fmtSize(sc.TextureData)})
	table.SetFooter([]string{"Total", " ", strings.TrimLeft(fmtSize(sc.VertexList, sc.NormalList, sc.UvList, sc.BvhNodeList, sc.MeshInstanceList, sc.EmissivePrimitives, sc.MaterialNodeList, sc.MaterialIndex, sc.TextureMetadata, sc.TextureData), " ")})
	table.Render()
	return buf.String()
}