mirror of
https://bitbucket.org/s_l_teichmann/mtsatellite
synced 2024-11-17 15:48:17 +01:00
Implemented a greedy search algorithm to figure out the block regions with are not fully covered after a rendering step.
This commit is contained in:
parent
9106d71363
commit
3a0b922a9e
@ -11,6 +11,11 @@ import (
|
||||
"math"
|
||||
)
|
||||
|
||||
type Area struct {
|
||||
X1, Z1 int16
|
||||
X2, Z2 int16
|
||||
}
|
||||
|
||||
type Renderer struct {
|
||||
width int
|
||||
height int
|
||||
@ -19,7 +24,6 @@ type Renderer struct {
|
||||
yBuffer []int32
|
||||
yMin []int32
|
||||
cBuffer []int32
|
||||
filled int
|
||||
Rejected int
|
||||
}
|
||||
|
||||
@ -140,7 +144,12 @@ func NewRenderer(xOfs, zOfs int16, width, height int) (renderer *Renderer) {
|
||||
}
|
||||
|
||||
func (r *Renderer) IsFilled() bool {
|
||||
return r.filled == r.width<<4*r.height<<4
|
||||
for _, y := range r.yMin {
|
||||
if y == math.MinInt32 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (r *Renderer) RenderBlock(block *Block, nameIndex map[string]int32) (err error) {
|
||||
@ -165,20 +174,18 @@ func (r *Renderer) RenderBlock(block *Block, nameIndex map[string]int32) (err er
|
||||
|
||||
w := r.width << 4
|
||||
ofs := int(bz)*w<<4 + int(bx)<<4
|
||||
yB := r.yBuffer
|
||||
|
||||
yMin := int32(math.MaxInt32)
|
||||
for z := 0; z < 16; z++ {
|
||||
for x := 0; x < 16; x++ {
|
||||
currentY := r.yBuffer[ofs]
|
||||
currentY := yB[ofs]
|
||||
if currentY < blockY {
|
||||
for y := 15; y >= 0; y-- {
|
||||
if c, ok := db.Content(x, y, z); ok {
|
||||
if r.cBuffer[ofs] == -1 {
|
||||
r.filled++
|
||||
}
|
||||
r.cBuffer[ofs] = c
|
||||
currentY = blockY + int32(y)
|
||||
r.yBuffer[ofs] = currentY
|
||||
yB[ofs] = currentY
|
||||
break
|
||||
}
|
||||
}
|
||||
@ -195,6 +202,99 @@ func (r *Renderer) RenderBlock(block *Block, nameIndex map[string]int32) (err er
|
||||
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) IsHigher() 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
|
||||
}
|
||||
|
||||
// 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.IsHigher() { // 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 {
|
||||
pw, ph := r.width<<4, r.height<<4
|
||||
image := image.NewRGBA(image.Rect(0, 0, pw, ph))
|
||||
|
Loading…
Reference in New Issue
Block a user