mirror of
https://bitbucket.org/s_l_teichmann/mtsatellite
synced 2025-01-11 01:10:17 +01:00
Simplified area coverage calculation a great deal.
This commit is contained in:
parent
4b92a6c722
commit
ca634f28ef
126
common/area.go
126
common/area.go
@ -4,7 +4,9 @@
|
|||||||
|
|
||||||
package common
|
package common
|
||||||
|
|
||||||
import "math"
|
import (
|
||||||
|
"math"
|
||||||
|
)
|
||||||
|
|
||||||
type Area struct {
|
type Area struct {
|
||||||
X1, Z1 int16
|
X1, Z1 int16
|
||||||
@ -28,79 +30,73 @@ func areasContain(areas []Area, x, z int16) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// UncoveredAreas implements a greedy algorithm to figure out
|
// recalculate implements a greedy algorithm to figure out
|
||||||
// a list of disjunct areas of free regions in the domain
|
// a list of disjunct areas of free regions in the domain
|
||||||
// to the (x, z) block plane.
|
// to the (x, z) block plane.
|
||||||
// oldAreas are searched and found free areas are appended
|
// oldAreas are searched and found free areas are appended
|
||||||
// to newAreas which ist return.
|
// to newAreas which ist return.
|
||||||
// This is useful to spatial query only blocks from db
|
// This is useful to spatial query only blocks from db
|
||||||
// that are not below already rendered blocks.
|
// that are not below already rendered blocks.
|
||||||
func UncoveredAreas(r *Renderer, newAreas, oldAreas []Area) []Area {
|
func (area Area) recalculate(r *Renderer, nareas []Area) []Area {
|
||||||
yM := r.yMin
|
yM := r.yMin
|
||||||
|
|
||||||
// Scan old areas.
|
const ex = 1
|
||||||
for _, oldArea := range oldAreas {
|
const ez = 2
|
||||||
for z := oldArea.Z1; z <= oldArea.Z2; z++ {
|
|
||||||
row := z * int16(r.width)
|
nas := len(nareas)
|
||||||
for x := oldArea.X1; x <= oldArea.X2; x++ {
|
|
||||||
// Uncovered and not in list of new areas?
|
for z := area.Z1; z <= area.Z2; z++ {
|
||||||
if yM[row+x] > math.MinInt32 || areasContain(newAreas, x, z) {
|
row := z * int16(r.width)
|
||||||
continue
|
for x := area.X1; x <= area.X2; x++ {
|
||||||
}
|
// Uncovered and not in list of new areas?
|
||||||
area := Area{X1: x, Z1: z, X2: x, Z2: z}
|
if yM[row+x] > math.MinInt32 || areasContain(nareas[nas:], x, z) {
|
||||||
// Try to extend the area in x and/or z till no further extension is possible.
|
continue
|
||||||
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 > oldArea.X2 {
|
|
||||||
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 > oldArea.Z2 {
|
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
a := 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.
|
||||||
|
ext:
|
||||||
|
for extend := ex | ez; extend != 0; {
|
||||||
|
// If we extending in both directions a the current area
|
||||||
|
// is higher than wide we gain more block if extend
|
||||||
|
// in the x direction first.
|
||||||
|
if (extend == ex|ez && a.higher()) || extend&ex == ex { // check x
|
||||||
|
nx := a.X2 + 1
|
||||||
|
if nx > area.X2 { // reached border of area
|
||||||
|
extend &= ^ex
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Check column right of the current area if its fully free.
|
||||||
|
for nz := a.Z1; nz <= a.Z2; nz++ {
|
||||||
|
if yM[nz*int16(r.width)+nx] > math.MinInt32 ||
|
||||||
|
areasContain(nareas[nas:], nx, nz) {
|
||||||
|
extend &= ^ex
|
||||||
|
continue ext
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// free -> extend
|
||||||
|
a.X2 = nx
|
||||||
|
} else if extend&ez == ez { // check z
|
||||||
|
nz := a.Z2 + 1
|
||||||
|
if nz > area.Z2 {
|
||||||
|
extend &= ^ez
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Check line right below the current area if its free.
|
||||||
|
row2 := nz * int16(r.width)
|
||||||
|
for nx := a.X1; nx <= a.X2; nx++ {
|
||||||
|
if yM[row2+nx] > math.MinInt32 ||
|
||||||
|
areasContain(nareas[nas:], nx, nz) {
|
||||||
|
extend &= ^ez
|
||||||
|
continue ext
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// free -> extend
|
||||||
|
a.Z2 = nz
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// At this point the area is extended to max.
|
||||||
|
nareas = append(nareas, a)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return newAreas
|
return nareas
|
||||||
}
|
}
|
||||||
|
@ -103,10 +103,10 @@ func (btc *BaseTileCreator) CreateTile(x, z int16, i, j int) (bool, error) {
|
|||||||
|
|
||||||
var c1, c2 Coord
|
var c1, c2 Coord
|
||||||
|
|
||||||
oareas := make([]Area, 0, tileWidth*tileHeight/2)
|
nareas := make([]Area, 0, tileWidth*tileHeight/2)
|
||||||
nareas := make([]Area, 1, tileWidth*tileHeight/2)
|
areas := make([]Area, 1, tileWidth*tileHeight/2)
|
||||||
|
|
||||||
nareas[0] = Area{
|
areas[0] = Area{
|
||||||
X1: 0, Z1: 0,
|
X1: 0, Z1: 0,
|
||||||
X2: int16(tileWidth) - 1, Z2: int16(tileHeight) - 1}
|
X2: int16(tileWidth) - 1, Z2: int16(tileHeight) - 1}
|
||||||
|
|
||||||
@ -118,9 +118,7 @@ func (btc *BaseTileCreator) CreateTile(x, z int16, i, j int) (bool, error) {
|
|||||||
c1.Y = max16(yRange[0], btc.yMin)
|
c1.Y = max16(yRange[0], btc.yMin)
|
||||||
c2.Y = min16(yRange[1], btc.yMax)
|
c2.Y = min16(yRange[1], btc.yMax)
|
||||||
|
|
||||||
var allCount int
|
for _, area := range areas {
|
||||||
|
|
||||||
for _, area := range nareas {
|
|
||||||
c1.X = area.X1 + x
|
c1.X = area.X1 + x
|
||||||
c1.Z = area.Z1 + z
|
c1.Z = area.Z1 + z
|
||||||
c2.X = area.X2 + x
|
c2.X = area.X2 + x
|
||||||
@ -131,18 +129,22 @@ func (btc *BaseTileCreator) CreateTile(x, z int16, i, j int) (bool, error) {
|
|||||||
if count, err = btc.client.QueryCuboid(query, btc.drawBlock); err != nil {
|
if count, err = btc.client.QueryCuboid(query, btc.drawBlock); err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
allCount += count
|
|
||||||
if err = btc.yOrder.Drain(btc.colors); err != nil {
|
if err = btc.yOrder.Drain(btc.colors); err != nil {
|
||||||
log.Printf("WARN: rendering block failed: %s\n", err)
|
log.Printf("WARN: rendering block failed: %s\n", err)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if allCount > 0 {
|
// If there where loaded blocks in this area recalculate coverage.
|
||||||
xareas := UncoveredAreas(btc.renderer, oareas, nareas)
|
if count > 0 {
|
||||||
if len(xareas) == 0 {
|
nareas = area.recalculate(btc.renderer, nareas)
|
||||||
break
|
} else {
|
||||||
|
nareas = append(nareas, area)
|
||||||
}
|
}
|
||||||
nareas, oareas = xareas, nareas[:0]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(nareas) == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
areas, nareas = nareas, areas[:0]
|
||||||
}
|
}
|
||||||
|
|
||||||
path := filepath.Join(btc.baseDir, strconv.Itoa(i), strconv.Itoa(j)+".png")
|
path := filepath.Join(btc.baseDir, strconv.Itoa(i), strconv.Itoa(j)+".png")
|
||||||
|
Loading…
Reference in New Issue
Block a user