mirror of
https://bitbucket.org/s_l_teichmann/mtsatellite
synced 2025-03-30 17:00:25 +02:00
Moved area coverage stuff out of renderer. It is an optimization to load
only needed blocks from db and has nothing to do with rendering.
This commit is contained in:
parent
3e3413566b
commit
003ce5035a
106
common/area.go
Normal file
106
common/area.go
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
// Copyright 2014, 2015, 2017 by Sascha L. Teichmann
|
||||||
|
// Use of this source code is governed by the MIT license
|
||||||
|
// that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package common
|
||||||
|
|
||||||
|
import "math"
|
||||||
|
|
||||||
|
type Area struct {
|
||||||
|
X1, Z1 int16
|
||||||
|
X2, Z2 int16
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a Area) contains(x, z int16) bool {
|
||||||
|
return x >= a.X1 && x <= a.X2 && z >= a.Z1 && z <= a.Z2
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a Area) higher() bool {
|
||||||
|
return a.Z2-a.Z1 > a.X2-a.X1
|
||||||
|
}
|
||||||
|
|
||||||
|
func areasContain(areas []Area, x, z int16) bool {
|
||||||
|
for _, r := range areas {
|
||||||
|
if r.contains(x, z) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// UncoveredAreas implements a greedy algorithm to figure out
|
||||||
|
// a list of disjunct areas of free regions in the domain
|
||||||
|
// to the (x, z) block plane.
|
||||||
|
// oldAreas are searched and found free areas are appended
|
||||||
|
// to newAreas which ist return.
|
||||||
|
// This is useful to spatial query only blocks from db
|
||||||
|
// that are not below already rendered blocks.
|
||||||
|
func UncoveredAreas(r *Renderer, newAreas, oldAreas []Area) []Area {
|
||||||
|
yM := r.yMin
|
||||||
|
|
||||||
|
// Scan old areas.
|
||||||
|
for _, oldArea := range oldAreas {
|
||||||
|
for z := oldArea.Z1; z <= oldArea.Z2; z++ {
|
||||||
|
row := z * int16(r.width)
|
||||||
|
for x := oldArea.X1; x <= oldArea.X2; x++ {
|
||||||
|
// Uncovered and not in list of new areas?
|
||||||
|
if yM[row+x] > math.MinInt32 || areasContain(newAreas, x, z) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
area := Area{X1: x, Z1: z, X2: x, Z2: z}
|
||||||
|
// Try to extend the area in x and/or z till no further extension is possible.
|
||||||
|
for extendDirs := 1 | 2; extendDirs != 0; {
|
||||||
|
var xFirst bool
|
||||||
|
// Try to extend in the direction with most gain
|
||||||
|
// of blocks.
|
||||||
|
if area.higher() { // Higher means to win more blocks in x direction.
|
||||||
|
xFirst = true
|
||||||
|
}
|
||||||
|
dirs:
|
||||||
|
for i := 0; i < 2; i++ {
|
||||||
|
if xFirst {
|
||||||
|
// Extension in x possible?
|
||||||
|
if extendDirs&1 == 1 {
|
||||||
|
nx := area.X2 + 1
|
||||||
|
if nx >= int16(r.width) {
|
||||||
|
extendDirs &= ^1
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Scan line below current area if its fully free.
|
||||||
|
for nz := area.Z1; nz <= area.Z2; nz++ {
|
||||||
|
if yM[nz*int16(r.width)+nx] > math.MinInt32 || areasContain(newAreas, nx, nz) {
|
||||||
|
extendDirs &= ^1
|
||||||
|
continue dirs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// free -> extend
|
||||||
|
area.X2 = nx
|
||||||
|
}
|
||||||
|
} else if extendDirs&2 == 2 {
|
||||||
|
// Symmetric case in z direction
|
||||||
|
nz := area.Z2 + 1
|
||||||
|
if nz >= int16(r.height) {
|
||||||
|
extendDirs &= ^2
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Scan line right beside the area if its free.
|
||||||
|
row2 := nz * int16(r.width)
|
||||||
|
for nx := area.X1; nx <= area.X2; nx++ {
|
||||||
|
if yM[row2+nx] > math.MinInt32 || areasContain(newAreas, nx, nz) {
|
||||||
|
extendDirs &= ^2
|
||||||
|
continue dirs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
area.Z2 = nz
|
||||||
|
}
|
||||||
|
// Switch to other search direction (x -> z or z -> x)
|
||||||
|
xFirst = !xFirst
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// At this point the area is extended to max.
|
||||||
|
newAreas = append(newAreas, area)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newAreas
|
||||||
|
}
|
@ -137,7 +137,7 @@ func (btc *BaseTileCreator) CreateTile(x, z int16, i, j int) (bool, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if allCount > 0 {
|
if allCount > 0 {
|
||||||
xareas := btc.renderer.UncoveredAreas(oareas, nareas)
|
xareas := UncoveredAreas(btc.renderer, oareas, nareas)
|
||||||
if len(xareas) == 0 {
|
if len(xareas) == 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -12,11 +12,6 @@ import (
|
|||||||
"math"
|
"math"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Area struct {
|
|
||||||
X1, Z1 int16
|
|
||||||
X2, Z2 int16
|
|
||||||
}
|
|
||||||
|
|
||||||
type Renderer struct {
|
type Renderer struct {
|
||||||
width int
|
width int
|
||||||
height int
|
height int
|
||||||
@ -286,100 +281,6 @@ func (r *Renderer) RenderBlock(block *Block, colors *Colors) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a Area) contains(x, z int16) bool {
|
|
||||||
return x >= a.X1 && x <= a.X2 && z >= a.Z1 && z <= a.Z2
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a Area) higher() bool {
|
|
||||||
return a.Z2-a.Z1 > a.X2-a.X1
|
|
||||||
}
|
|
||||||
|
|
||||||
func areasContain(areas []Area, x, z int16) bool {
|
|
||||||
for _, r := range areas {
|
|
||||||
if r.contains(x, z) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// UncoveredAreas implements a greedy algorithm to figure out
|
|
||||||
// a list of disjunct areas of free regions in the domain
|
|
||||||
// to the (x, z) block plane.
|
|
||||||
// oldAreas are searched and found free areas are appended
|
|
||||||
// to newAreas which ist return.
|
|
||||||
// This is useful to spatial query only blocks from db
|
|
||||||
// that are not below already rendered blocks.
|
|
||||||
func (r *Renderer) UncoveredAreas(newAreas, oldAreas []Area) []Area {
|
|
||||||
yM := r.yMin
|
|
||||||
|
|
||||||
// Scan old areas.
|
|
||||||
for _, oldArea := range oldAreas {
|
|
||||||
for z := oldArea.Z1; z <= oldArea.Z2; z++ {
|
|
||||||
row := z * int16(r.width)
|
|
||||||
for x := oldArea.X1; x <= oldArea.X2; x++ {
|
|
||||||
// Uncovered and not in list of new areas?
|
|
||||||
if yM[row+x] > math.MinInt32 || areasContain(newAreas, x, z) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
area := Area{X1: x, Z1: z, X2: x, Z2: z}
|
|
||||||
// Try to extend the area in x and/or z till no further extension is possible.
|
|
||||||
for extendDirs := 1 | 2; extendDirs != 0; {
|
|
||||||
var xFirst bool
|
|
||||||
// Try to extend in the direction with most gain
|
|
||||||
// of blocks.
|
|
||||||
if area.higher() { // Higher means to win more blocks in x direction.
|
|
||||||
xFirst = true
|
|
||||||
}
|
|
||||||
dirs:
|
|
||||||
for i := 0; i < 2; i++ {
|
|
||||||
if xFirst {
|
|
||||||
// Extension in x possible?
|
|
||||||
if extendDirs&1 == 1 {
|
|
||||||
nx := area.X2 + 1
|
|
||||||
if nx >= int16(r.width) {
|
|
||||||
extendDirs &= ^1
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// Scan line below current area if its fully free.
|
|
||||||
for nz := area.Z1; nz <= area.Z2; nz++ {
|
|
||||||
if yM[nz*int16(r.width)+nx] > math.MinInt32 || areasContain(newAreas, nx, nz) {
|
|
||||||
extendDirs &= ^1
|
|
||||||
continue dirs
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// free -> extend
|
|
||||||
area.X2 = nx
|
|
||||||
}
|
|
||||||
} else if extendDirs&2 == 2 {
|
|
||||||
// Symmetric case in z direction
|
|
||||||
nz := area.Z2 + 1
|
|
||||||
if nz >= int16(r.height) {
|
|
||||||
extendDirs &= ^2
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// Scan line right beside the area if its free.
|
|
||||||
row2 := nz * int16(r.width)
|
|
||||||
for nx := area.X1; nx <= area.X2; nx++ {
|
|
||||||
if yM[row2+nx] > math.MinInt32 || areasContain(newAreas, nx, nz) {
|
|
||||||
extendDirs &= ^2
|
|
||||||
continue dirs
|
|
||||||
}
|
|
||||||
}
|
|
||||||
area.Z2 = nz
|
|
||||||
}
|
|
||||||
// Switch to other search direction (x -> z or z -> x)
|
|
||||||
xFirst = !xFirst
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// At this point the area is extended to max.
|
|
||||||
newAreas = append(newAreas, area)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return newAreas
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Renderer) CreateImage(colors []color.RGBA, background color.RGBA) *image.RGBA {
|
func (r *Renderer) CreateImage(colors []color.RGBA, background color.RGBA) *image.RGBA {
|
||||||
pw, ph := r.width<<4, r.height<<4
|
pw, ph := r.width<<4, r.height<<4
|
||||||
image := image.NewRGBA(image.Rect(0, 0, pw, ph))
|
image := image.NewRGBA(image.Rect(0, 0, pw, ph))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user