2018-09-05 13:53:09 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2018-09-17 19:11:04 +00:00
|
|
|
"github.com/divan/graphx/graph"
|
|
|
|
"github.com/divan/graphx/layout"
|
2018-09-20 12:41:24 +00:00
|
|
|
"github.com/divan/three"
|
2018-09-05 13:53:09 +00:00
|
|
|
)
|
|
|
|
|
2018-10-12 20:34:30 +00:00
|
|
|
// 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
|
|
|
|
}
|
|
|
|
|
2018-09-20 17:38:43 +00:00
|
|
|
// CreateObjects creates WebGL primitives from layout/graphGroup data.
|
2018-09-17 19:11:04 +00:00
|
|
|
// 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) {
|
2018-10-12 20:34:30 +00:00
|
|
|
w.positions = positions
|
|
|
|
|
2018-09-20 17:38:43 +00:00
|
|
|
w.graphGroup = three.NewGroup()
|
|
|
|
w.scene.Add(w.graphGroup)
|
2018-09-05 13:53:09 +00:00
|
|
|
|
2018-09-20 17:38:43 +00:00
|
|
|
w.nodesGroup = three.NewGroup()
|
|
|
|
w.graphGroup.Add(w.nodesGroup)
|
2018-09-05 13:53:09 +00:00
|
|
|
|
2018-09-20 17:38:43 +00:00
|
|
|
w.edgesGroup = three.NewGroup()
|
|
|
|
w.graphGroup.Add(w.edgesGroup)
|
2018-09-17 19:11:04 +00:00
|
|
|
|
2018-10-12 20:34:30 +00:00
|
|
|
w.createNodes()
|
|
|
|
w.createEdges(links)
|
|
|
|
|
|
|
|
// once we know nodes, we can prepare fancy stuff
|
|
|
|
w.wobbling = NewWobbling(w.positions)
|
2018-09-05 14:09:56 +00:00
|
|
|
}
|
|
|
|
|
2018-10-12 20:34:30 +00:00
|
|
|
func (w *WebGLScene) createNodes() {
|
2018-09-05 14:09:56 +00:00
|
|
|
scale := 2.0
|
|
|
|
geometry := NewEthereumGeometry(scale)
|
|
|
|
material := NewNodeMaterial()
|
2018-10-12 20:34:30 +00:00
|
|
|
for id, node := range w.positions {
|
|
|
|
mesh := &Mesh{
|
|
|
|
ID: id,
|
|
|
|
Mesh: three.NewMesh(geometry, material),
|
|
|
|
}
|
2018-09-05 13:53:09 +00:00
|
|
|
mesh.Position.Set(node.X, node.Y, node.Z)
|
2018-10-12 20:34:30 +00:00
|
|
|
w.nodesGroup.Add(mesh.Mesh)
|
2018-09-20 17:38:43 +00:00
|
|
|
w.nodes = append(w.nodes, mesh)
|
2018-09-05 13:53:09 +00:00
|
|
|
}
|
2018-09-05 14:09:56 +00:00
|
|
|
}
|
2018-09-05 13:53:09 +00:00
|
|
|
|
2018-10-12 20:34:30 +00:00
|
|
|
func (w *WebGLScene) createEdges(links []*graph.Link) {
|
2018-09-20 19:16:21 +00:00
|
|
|
material := NewEdgeMaterial()
|
2018-09-17 19:11:04 +00:00
|
|
|
for _, link := range links {
|
2018-09-05 13:53:09 +00:00
|
|
|
from := link.From()
|
|
|
|
to := link.To()
|
2018-10-12 20:34:30 +00:00
|
|
|
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)
|
2018-09-05 13:53:09 +00:00
|
|
|
|
2018-10-12 20:34:30 +00:00
|
|
|
geom.AddAttribute("position", attr)
|
2018-09-05 13:53:09 +00:00
|
|
|
|
2018-10-12 20:34:30 +00:00
|
|
|
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),
|
|
|
|
}
|
|
|
|
w.edgesGroup.Add(line.Line)
|
2018-09-20 17:38:43 +00:00
|
|
|
w.lines = append(w.lines, line)
|
2018-09-05 13:53:09 +00:00
|
|
|
}
|
|
|
|
}
|
2018-09-17 19:11:04 +00:00
|
|
|
|
2018-10-12 20:34:30 +00:00
|
|
|
// 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)
|
|
|
|
}
|
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-17 19:11:04 +00:00
|
|
|
// RemoveObjects removes WebGL primitives, cleaning up scene.
|
|
|
|
func (w *WebGLScene) RemoveObjects() {
|
2018-09-20 17:38:43 +00:00
|
|
|
if w.nodesGroup != nil {
|
|
|
|
for _, child := range w.nodesGroup.Children {
|
|
|
|
w.nodesGroup.Remove(child)
|
2018-09-20 13:30:20 +00:00
|
|
|
}
|
|
|
|
}
|
2018-09-20 17:38:43 +00:00
|
|
|
if w.edgesGroup != nil {
|
|
|
|
for _, child := range w.edgesGroup.Children {
|
|
|
|
w.edgesGroup.Remove(child)
|
2018-09-20 13:30:20 +00:00
|
|
|
}
|
|
|
|
}
|
2018-09-20 17:38:43 +00:00
|
|
|
|
|
|
|
w.nodes, w.lines = nil, nil
|
2018-10-12 20:34:30 +00:00
|
|
|
w.positions = nil
|
2018-09-20 17:38:43 +00:00
|
|
|
w.graphGroup, w.nodesGroup, w.edgesGroup = nil, nil, nil
|
2018-09-17 19:11:04 +00:00
|
|
|
}
|