/
scene.go
121 lines (101 loc) 路 2.45 KB
/
scene.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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
// Copyright 2021 Changkun Ou <changkun.de>. All rights reserved.
// Use of this source code is governed by a GPLv3 license that
// can be found in the LICENSE file.
package scene
import (
"changkun.de/x/ddd/camera"
"changkun.de/x/ddd/geometry"
"changkun.de/x/ddd/geometry/primitive"
"changkun.de/x/ddd/math"
"changkun.de/x/ddd/object"
)
// Scene is a scene graph
type Scene struct {
root *Group
camera camera.Interface
}
func NewScene() *Scene {
s := &Scene{}
rootGroup := newGroup()
rootGroup.name = "root"
rootGroup.object = nil
rootGroup.root = s
s.root = rootGroup
return s
}
func (s *Scene) Add(geo ...object.Object) *Group {
s.root.Add(geo...)
return s.root
}
func (s *Scene) SetCamera(c camera.Interface) {
s.camera = c
}
func (s *Scene) GetCamera() camera.Interface {
return s.camera
}
func (s *Scene) IterObjects(iter func(o object.Object, modelMatrix math.Matrix) bool) {
for i := range s.root.children {
s.root.children[i].IterObjects(func(o object.Object, modelMatrix math.Matrix) bool {
iter(o, s.root.ModelMatrix().MulM(modelMatrix))
return true
})
}
}
func (s *Scene) Center() math.Vector {
aabb := &primitive.AABB{
Min: math.NewVector(0, 0, 0, 1),
Max: math.NewVector(0, 0, 0, 1),
}
s.IterObjects(func(o object.Object, modelMatrix math.Matrix) bool {
if o.Type() != object.TypeMesh {
return true
}
mesh := o.(geometry.Mesh)
aabb.Add(mesh.AABB())
return true
})
return aabb.Min.Add(aabb.Max).Pos()
}
var _ object.Object = &Group{}
// Group is a group of geometry objects, and also implements
// the geometry.Object interface.
type Group struct {
math.TransformContext
name string
root *Scene
object object.Object
parent *Group
children []*Group
}
func newGroup() *Group {
g := &Group{
name: "",
root: nil,
object: nil,
parent: nil,
children: []*Group{},
}
g.ResetContext()
return g
}
func (g *Group) Type() object.Type {
return object.TypeGroup
}
func (g *Group) Add(geo ...object.Object) *Group {
for i := range geo {
gg := newGroup()
gg.root = g.root
gg.parent = g
gg.object = geo[i]
g.children = append(g.children, gg)
}
return g
}
func (g *Group) IterObjects(iter func(o object.Object, modelMatrix math.Matrix) bool) {
iter(g.object, g.ModelMatrix().MulM(g.object.ModelMatrix()))
for i := range g.children {
g.children[i].IterObjects(func(o object.Object, modelMatrix math.Matrix) bool {
return iter(o, g.ModelMatrix().MulM(o.ModelMatrix()))
})
}
}