less cache, more compute
This commit is contained in:
parent
adf933f497
commit
7b6dd76f79
1 changed files with 30 additions and 31 deletions
|
@ -38,7 +38,6 @@ type DrawDAG struct {
|
||||||
dag
|
dag
|
||||||
boxCache map[DrawBoxer]geom.Box // used to find components that moved
|
boxCache map[DrawBoxer]geom.Box // used to find components that moved
|
||||||
chunks map[image.Point]drawerSet // chunk coord -> drawers with bounding rects intersecting chunk
|
chunks map[image.Point]drawerSet // chunk coord -> drawers with bounding rects intersecting chunk
|
||||||
chunksRev map[DrawBoxer]image.Rectangle // comopnent -> rectangle of chunk coords
|
|
||||||
game *Game
|
game *Game
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,7 +110,6 @@ func (d *DrawDAG) Prepare(game *Game) error {
|
||||||
d.dag = make(dag)
|
d.dag = make(dag)
|
||||||
d.boxCache = make(map[DrawBoxer]geom.Box)
|
d.boxCache = make(map[DrawBoxer]geom.Box)
|
||||||
d.chunks = make(map[image.Point]drawerSet)
|
d.chunks = make(map[image.Point]drawerSet)
|
||||||
d.chunksRev = make(map[DrawBoxer]image.Rectangle)
|
|
||||||
d.game = game
|
d.game = game
|
||||||
|
|
||||||
// Because Game.LoadAndPrepare calls Prepare in a post-order walk, all the
|
// Because Game.LoadAndPrepare calls Prepare in a post-order walk, all the
|
||||||
|
@ -132,18 +130,19 @@ func (d *DrawDAG) String() string { return "DrawDAG" }
|
||||||
func (d *DrawDAG) Update() error {
|
func (d *DrawDAG) Update() error {
|
||||||
// Re-evaluate bounding boxes for all descendants. If a box has changed,
|
// Re-evaluate bounding boxes for all descendants. If a box has changed,
|
||||||
// fix up the edges by removing and re-adding the vertex.
|
// fix up the edges by removing and re-adding the vertex.
|
||||||
// Thanks once again to postorder traversal, this happens after all
|
// Thanks once again to postorder traversal in Game.Update, this happens
|
||||||
// descendant updates.
|
// after all descendant updates.
|
||||||
|
// TODO: more flexible update ordering system...
|
||||||
var readd []DrawBoxer
|
var readd []DrawBoxer
|
||||||
for db, bb := range d.boxCache {
|
for db, bb := range d.boxCache {
|
||||||
nbb := db.BoundingBox()
|
nbb := db.BoundingBox()
|
||||||
if bb != nbb {
|
if bb != nbb {
|
||||||
d.Unregister(db)
|
d.unregisterOne(db)
|
||||||
readd = append(readd, db)
|
readd = append(readd, db)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, db := range readd {
|
for _, db := range readd {
|
||||||
d.Register(db, nil)
|
d.registerOne(db)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -190,34 +189,34 @@ func (d *DrawDAG) registerOne(x DrawBoxer) {
|
||||||
|
|
||||||
// Update the reverse chunk map
|
// Update the reverse chunk map
|
||||||
xbr := xb.BoundingRect(d.game.Projection)
|
xbr := xb.BoundingRect(d.game.Projection)
|
||||||
revr := image.Rectangle{
|
min := xbr.Min.Div(d.ChunkSize)
|
||||||
Min: xbr.Min.Div(d.ChunkSize),
|
max := xbr.Max.Sub(image.Pt(1, 1)).Div(d.ChunkSize)
|
||||||
Max: xbr.Max.Sub(image.Pt(1, 1)).Div(d.ChunkSize),
|
|
||||||
}
|
|
||||||
d.chunksRev[x] = revr
|
|
||||||
|
|
||||||
// Find possible edges between x and items in the overlapping cells.
|
// Find possible edges between x and items in the overlapping chunks.
|
||||||
// First, a set of all the items in those cells.
|
// First, a set of all the items in those chunks.
|
||||||
cand := make(drawerSet)
|
cand := make(drawerSet)
|
||||||
var p image.Point
|
var p image.Point
|
||||||
for p.Y = revr.Min.Y; p.Y <= revr.Max.Y; p.Y++ {
|
for p.Y = min.Y; p.Y <= max.Y; p.Y++ {
|
||||||
for p.X = revr.Min.X; p.X <= revr.Max.X; p.X++ {
|
for p.X = min.X; p.X <= max.X; p.X++ {
|
||||||
cell := d.chunks[p]
|
chunk := d.chunks[p]
|
||||||
if cell == nil {
|
if chunk == nil {
|
||||||
cell = make(drawerSet)
|
d.chunks[p] = drawerSet{x: {}}
|
||||||
d.chunks[p] = cell
|
continue
|
||||||
}
|
}
|
||||||
// Merge cell contents into cand
|
// Merge chunk contents into cand
|
||||||
for c := range cell {
|
for c := range chunk {
|
||||||
cand[c] = struct{}{}
|
cand[c] = struct{}{}
|
||||||
}
|
}
|
||||||
// Add x to cell
|
// Add x to chunk
|
||||||
cell[x] = struct{}{}
|
chunk[x] = struct{}{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Add edges between x and elements of cand
|
// Add edges between x and elements of cand
|
||||||
πsign := d.game.Projection.Sign()
|
πsign := d.game.Projection.Sign()
|
||||||
for c := range cand {
|
for c := range cand {
|
||||||
|
if x == c {
|
||||||
|
continue
|
||||||
|
}
|
||||||
y := c.(DrawBoxer)
|
y := c.(DrawBoxer)
|
||||||
// Bounding rectangle overlap test
|
// Bounding rectangle overlap test
|
||||||
// No overlap, no edge.
|
// No overlap, no edge.
|
||||||
|
@ -251,14 +250,14 @@ func (d *DrawDAG) Unregister(component interface{}) {
|
||||||
|
|
||||||
func (d *DrawDAG) unregisterOne(x DrawBoxer) {
|
func (d *DrawDAG) unregisterOne(x DrawBoxer) {
|
||||||
// Remove from chunk map
|
// Remove from chunk map
|
||||||
revr := d.chunksRev[x]
|
xbr := d.boxCache[x].BoundingRect(d.game.Projection)
|
||||||
for j := revr.Min.Y; j <= revr.Max.Y; j++ {
|
min := xbr.Min.Div(d.ChunkSize)
|
||||||
for i := revr.Min.X; i <= revr.Max.X; i++ {
|
max := xbr.Max.Sub(image.Pt(1, 1)).Div(d.ChunkSize)
|
||||||
|
for j := min.Y; j <= max.Y; j++ {
|
||||||
|
for i := min.X; i <= max.X; i++ {
|
||||||
delete(d.chunks[image.Pt(i, j)], x)
|
delete(d.chunks[image.Pt(i, j)], x)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Remove from reverse chunk map
|
|
||||||
delete(d.chunksRev, x)
|
|
||||||
// Remove from box cache
|
// Remove from box cache
|
||||||
delete(d.boxCache, x)
|
delete(d.boxCache, x)
|
||||||
// Remove from DAG
|
// Remove from DAG
|
||||||
|
|
Loading…
Reference in a new issue