-
Notifications
You must be signed in to change notification settings - Fork 5
/
objects.go
127 lines (108 loc) · 3.16 KB
/
objects.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
122
123
124
125
126
127
package main
import (
"github.com/divan/graphx/graph"
"github.com/divan/graphx/layout"
"github.com/divan/three"
)
// Mesh represents three.Mesh, and holds some additional metadata.
type Mesh struct {
ID string
*three.Mesh
}
// Line represents three.Line, and holds some additional metadata.
type Line struct {
From string
To string
*three.Line
}
// CreateObjects creates WebGL primitives from layout/graphGroup data.
// TODO(divan): change positions and links types to something more clear and readable
func (w *WebGLScene) CreateObjects(positions map[string]*layout.Object, links []*graph.Link) {
w.positions = positions
w.graphGroup = three.NewGroup()
w.graphGroup.MatrixAutoUpdate = false
w.scene.Add(w.graphGroup)
w.nodesGroup = three.NewGroup()
w.nodesGroup.MatrixAutoUpdate = false
w.graphGroup.Add(w.nodesGroup)
w.edgesGroup = three.NewGroup()
w.edgesGroup.MatrixAutoUpdate = false
w.graphGroup.Add(w.edgesGroup)
w.createNodes()
w.createEdges(links)
// once we know nodes, we can prepare fancy stuff
w.wobbling = NewWobbling(w.positions)
}
func (w *WebGLScene) createNodes() {
scale := 2.0
geometry := NewEthereumGeometry(scale)
material := NewNodeMaterial()
for id, node := range w.positions {
mesh := &Mesh{
ID: id,
Mesh: three.NewMesh(geometry, material),
}
mesh.Position.Set(node.X(), node.Y(), node.Z())
mesh.MatrixAutoUpdate = false
mesh.UpdateMatrix()
w.nodesGroup.Add(mesh.Mesh)
w.nodes = append(w.nodes, mesh)
}
}
func (w *WebGLScene) createEdges(links []*graph.Link) {
material := NewEdgeMaterial()
for _, link := range links {
from := link.From()
to := link.To()
start := w.positions[from]
end := w.positions[to]
var geom = three.NewBufferGeometry()
var positions = make([]float32, 2*3) // 2 positions (start and end), 3 coords per each
var attr = three.NewBufferAttribute(positions, 3)
geom.AddAttribute("position", attr)
attr.SetXYZ(0, start.X(), start.Y(), start.Z())
attr.SetXYZ(1, end.X(), end.Y(), end.Z())
attr.NeedsUpdate = true
line := &Line{
From: from,
To: to,
Line: three.NewLine(geom, material),
}
line.MatrixAutoUpdate = false
w.edgesGroup.Add(line.Line)
w.lines = append(w.lines, line)
}
}
// updatePositions sets meshes/lines positions from positions (probably
// recalculated somewhere else)
func (w *WebGLScene) updatePositions() {
for _, node := range w.nodes {
pos := w.positions[node.ID]
node.Position.Set(pos.X(), pos.Y(), pos.Z())
node.UpdateMatrix()
}
for i := range w.lines {
start := w.positions[w.lines[i].From]
end := w.positions[w.lines[i].To]
attr := w.lines[i].Geometry.GetAttribute("position")
attr.SetXYZ(0, start.X(), start.Y(), start.Z())
attr.SetXYZ(1, end.X(), end.Y(), end.Z())
attr.NeedsUpdate = true
}
}
// RemoveObjects removes WebGL primitives, cleaning up scene.
func (w *WebGLScene) RemoveObjects() {
if w.nodesGroup != nil {
for _, child := range w.nodesGroup.Children {
w.nodesGroup.Remove(child)
}
}
if w.edgesGroup != nil {
for _, child := range w.edgesGroup.Children {
w.edgesGroup.Remove(child)
}
}
w.nodes, w.lines = nil, nil
w.positions = nil
w.graphGroup, w.nodesGroup, w.edgesGroup = nil, nil, nil
}