forked from fogleman/pack3d
/
main.go
92 lines (78 loc) · 1.82 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
package main
import (
"fmt"
"math"
"math/rand"
"os"
"strconv"
"time"
"github.com/fogleman/fauxgl"
"github.com/fogleman/pack3d/pack3d"
)
const (
bvhDetail = 8
annealingIterations = 2000000
)
func timed(name string) func() {
if len(name) > 0 {
fmt.Printf("%s... ", name)
}
start := time.Now()
return func() {
fmt.Println(time.Since(start))
}
}
func main() {
var done func()
rand.Seed(time.Now().UTC().UnixNano())
model := pack3d.NewModel()
count := 1
ok := false
var totalVolume float64
for _, arg := range os.Args[1:] {
_count, err := strconv.ParseInt(arg, 0, 0)
if err == nil {
count = int(_count)
continue
}
done = timed(fmt.Sprintf("loading mesh %s", arg))
mesh, err := fauxgl.LoadMesh(arg)
if err != nil {
panic(err)
}
done()
totalVolume += mesh.BoundingBox().Volume()
size := mesh.BoundingBox().Size()
fmt.Printf(" %d triangles\n", len(mesh.Triangles))
fmt.Printf(" %g x %g x %g\n", size.X, size.Y, size.Z)
done = timed("centering mesh")
mesh.Center()
done()
done = timed("building bvh tree")
model.Add(mesh, bvhDetail, count)
ok = true
done()
}
if !ok {
fmt.Println("Usage: pack3d N1 mesh1.stl N2 mesh2.stl ...")
fmt.Println(" - Packs N copies of each mesh into as small of a volume as possible.")
fmt.Println(" - Runs forever, looking for the best packing.")
fmt.Println(" - Results are written to disk whenever a new best is found.")
return
}
side := math.Pow(totalVolume, 1.0/3)
model.Deviation = side / 32
best := 1e9
for {
model = model.Pack(annealingIterations, nil)
score := model.Energy()
if score < best {
best = score
done = timed("writing mesh")
model.Mesh().SaveSTL(fmt.Sprintf("pack3d-%.3f.stl", score))
// model.TreeMesh().SaveSTL(fmt.Sprintf("out%dtree.stl", int(score*100000)))
done()
}
model.Reset()
}
}