-
Notifications
You must be signed in to change notification settings - Fork 16
/
process-merge.go
105 lines (92 loc) · 2.44 KB
/
process-merge.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
93
94
95
96
97
98
99
100
101
102
103
104
105
package main
import (
"fmt"
"strings"
"github.com/jonnenauha/obj-simplify/objectfile"
)
type Merge struct{}
type merger struct {
Material string
Objects []*objectfile.Object
}
func (processor Merge) Name() string {
return "Merge"
}
func (processor Merge) Desc() string {
return "Merges objects and groups with the same material into a single mesh."
}
func (processor Merge) Execute(obj *objectfile.OBJ) error {
// use an array to preserve original order and
// to produce always the same output with same input.
// Map will 'randomize' keys in golang on each run.
materials := make([]*merger, 0)
for _, child := range obj.Objects {
// skip children that do not declare faces etc.
if len(child.VertexData) == 0 {
continue
}
found := false
for _, m := range materials {
if m.Material == child.Material {
m.Objects = append(m.Objects, child)
found = true
break
}
}
if !found {
materials = append(materials, &merger{
Material: child.Material,
Objects: []*objectfile.Object{child},
})
}
}
logInfo(" - Found %d unique materials", len(materials))
mergeName := func(objects []*objectfile.Object) string {
parts := []string{}
for _, child := range objects {
if len(child.Name) > 0 {
parts = append(parts, child.Name)
}
}
if len(parts) == 0 {
parts = append(parts, "Unnamed")
}
name := strings.Join(parts, " ")
// we might be merging hundreds or thousands of objects, at which point
// the name becomes huge. Clamp with arbitrary 256 chars.
if len(name) > 256 {
name = ""
for i, child := range objects {
if len(child.Name) == 0 {
continue
}
if len(name)+len(child.Name) < 256 {
name += child.Name + " "
} else {
name += fmt.Sprintf("(and %d others)", len(objects)-i)
break
}
}
}
return name
}
mergeComments := func(objects []*objectfile.Object) (comments []string) {
for _, child := range objects {
if len(child.Comments) > 0 {
comments = append(comments, child.Comments...)
}
}
return comments
}
// reset objects, we are about to rewrite them
obj.Objects = make([]*objectfile.Object, 0)
for _, merger := range materials {
src := merger.Objects[0]
child := obj.CreateObject(src.Type, mergeName(merger.Objects), merger.Material)
child.Comments = mergeComments(merger.Objects)
for _, original := range merger.Objects {
child.VertexData = append(child.VertexData, original.VertexData...)
}
}
return nil
}