mirror of
https://bitbucket.org/s_l_teichmann/mtsatellite
synced 2024-11-08 03:00:26 +01:00
Render transparent tiles if command line flag is set.
This commit is contained in:
parent
2aa9ee0e24
commit
8452a26fcd
|
@ -48,6 +48,7 @@ func order(a, b int) (int, int) {
|
|||
func createBaseLevel(
|
||||
address string,
|
||||
xMin, zMin, xMax, zMax int,
|
||||
transparent bool,
|
||||
colorsFile, outDir string,
|
||||
numWorkers int) (err error) {
|
||||
|
||||
|
@ -71,7 +72,7 @@ func createBaseLevel(
|
|||
return
|
||||
}
|
||||
done.Add(1)
|
||||
btc := common.NewBaseTileCreator(client, colors, baseDir, false)
|
||||
btc := common.NewBaseTileCreator(client, colors, transparent, baseDir, false)
|
||||
go createTiles(btc, jobs, &done)
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ func main() {
|
|||
numWorkers int
|
||||
skipBaseLevel bool
|
||||
skipPyramid bool
|
||||
transparent bool
|
||||
)
|
||||
|
||||
flag.IntVar(&port, "port", 6379, "port to of mtredisalize server")
|
||||
|
@ -39,6 +40,8 @@ func main() {
|
|||
flag.BoolVar(&skipBaseLevel, "sb", false, "Do not generate base level tiles (shorthand)")
|
||||
flag.BoolVar(&skipPyramid, "skip-pyramid", false, "Do not generate pyramid tiles")
|
||||
flag.BoolVar(&skipPyramid, "sp", false, "Do not generate pyramid tiles (shorthand)")
|
||||
flag.BoolVar(&transparent, "transparent", false, "Render transparent blocks.")
|
||||
flag.BoolVar(&transparent, "t", false, "Render transparent blocks (shorthand).")
|
||||
|
||||
flag.Parse()
|
||||
|
||||
|
@ -46,7 +49,12 @@ func main() {
|
|||
if !skipBaseLevel {
|
||||
address := fmt.Sprintf("%s:%d", host, port)
|
||||
if err = createBaseLevel(
|
||||
address, xMin, zMin, xMax, zMax, colorsFile, outDir, numWorkers); err != nil {
|
||||
address,
|
||||
xMin, zMin, xMax, zMax,
|
||||
transparent,
|
||||
colorsFile,
|
||||
outDir,
|
||||
numWorkers); err != nil {
|
||||
log.Fatalf("Creating base level tiles failed: %s", err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ func main() {
|
|||
colorsfile string
|
||||
outfile string
|
||||
shaded bool
|
||||
transparent bool
|
||||
)
|
||||
|
||||
flag.IntVar(&port, "port", 6379, "port to of mtredisalize server")
|
||||
|
@ -41,6 +42,7 @@ func main() {
|
|||
flag.StringVar(&outfile, "output", "out.png", "image file of result")
|
||||
flag.StringVar(&outfile, "o", "out.png", "image file of result (shorthand)")
|
||||
flag.BoolVar(&shaded, "shaded", true, "draw relief")
|
||||
flag.BoolVar(&transparent, "transparent", false, "render transparent blocks")
|
||||
|
||||
flag.Parse()
|
||||
|
||||
|
@ -70,7 +72,7 @@ func main() {
|
|||
q1x, q1y, q1z := int16(x), int16(y), int16(z)
|
||||
q2x, q2y, q2z := q1x+int16(width)-1, q1y+int16(depth)-1, q1z+int16(height)-1
|
||||
|
||||
renderer := common.NewRenderer(width, height)
|
||||
renderer := common.NewRenderer(width, height, transparent)
|
||||
renderer.SetPos(q1x, q1z)
|
||||
yOrder := common.NewYOrder(renderer, 512)
|
||||
|
||||
|
@ -106,7 +108,7 @@ func main() {
|
|||
if shaded {
|
||||
image = renderer.CreateShadedImage(
|
||||
16, 16, (width-2)*16, (height-2)*16,
|
||||
colors.Colors, color.RGBA{R: 0xff, G: 0xff, B: 0xff, A: 0xff})
|
||||
colors, color.RGBA{R: 0xff, G: 0xff, B: 0xff, A: 0xff})
|
||||
} else {
|
||||
image = renderer.CreateImage(
|
||||
colors.Colors, color.RGBA{R: 0xff, G: 0xff, B: 0xff, A: 0xff})
|
||||
|
|
|
@ -17,14 +17,15 @@ import (
|
|||
|
||||
func main() {
|
||||
var (
|
||||
webPort int
|
||||
webHost string
|
||||
webDir string
|
||||
mapDir string
|
||||
redisPort int
|
||||
redisHost string
|
||||
colorsFile string
|
||||
workers int
|
||||
webPort int
|
||||
webHost string
|
||||
webDir string
|
||||
mapDir string
|
||||
redisPort int
|
||||
redisHost string
|
||||
colorsFile string
|
||||
workers int
|
||||
transparent bool
|
||||
)
|
||||
flag.IntVar(&webPort, "web-port", 8808, "port of the web server")
|
||||
flag.IntVar(&webPort, "p", 8808, "port of the web server (shorthand)")
|
||||
|
@ -41,6 +42,8 @@ func main() {
|
|||
flag.IntVar(&workers, "workers", 1, "number of workers to render tiles")
|
||||
flag.StringVar(&colorsFile, "colors", "colors.txt", "colors used to render map tiles.")
|
||||
flag.StringVar(&colorsFile, "c", "colors.txt", "colors used to render map tiles (shorthand).")
|
||||
flag.BoolVar(&transparent, "transparent", false, "Render transparent blocks.")
|
||||
flag.BoolVar(&transparent, "t", false, "Render transparent blocks (shorthand).")
|
||||
|
||||
flag.Parse()
|
||||
|
||||
|
@ -56,7 +59,7 @@ func main() {
|
|||
log.Fatalf("ERROR: problem loading colors: %s", err)
|
||||
}
|
||||
redisAddress := fmt.Sprintf("%s:%d", redisHost, redisPort)
|
||||
tu := newTileUpdater(mapDir, redisAddress, colors, workers)
|
||||
tu := newTileUpdater(mapDir, redisAddress, colors, transparent, workers)
|
||||
go tu.doUpdates()
|
||||
router.Path("/update").Methods("POST").Handler(tu)
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ type tileUpdater struct {
|
|||
redisAddress string
|
||||
colors *common.Colors
|
||||
workers int
|
||||
transparent bool
|
||||
cond *sync.Cond
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
@ -56,12 +57,18 @@ func (c xz) parent() xzm {
|
|||
Mask: 1 << (zr<<1 | xr)}
|
||||
}
|
||||
|
||||
func newTileUpdater(mapDir, redisAddress string, colors *common.Colors, workers int) *tileUpdater {
|
||||
func newTileUpdater(
|
||||
mapDir, redisAddress string,
|
||||
colors *common.Colors,
|
||||
transparent bool,
|
||||
workers int) *tileUpdater {
|
||||
|
||||
tu := tileUpdater{
|
||||
mapDir: mapDir,
|
||||
redisAddress: redisAddress,
|
||||
changes: map[xz]bool{},
|
||||
colors: colors,
|
||||
transparent: transparent,
|
||||
workers: workers}
|
||||
tu.cond = sync.NewCond(&tu.mu)
|
||||
return &tu
|
||||
|
@ -113,7 +120,7 @@ func (tu *tileUpdater) doUpdates() {
|
|||
log.Printf("WARN: Cannot connect to redis server: %s", err)
|
||||
continue
|
||||
}
|
||||
btc := common.NewBaseTileCreator(client, tu.colors, baseDir, true)
|
||||
btc := common.NewBaseTileCreator(client, tu.colors, tu.transparent, baseDir, true)
|
||||
done.Add(1)
|
||||
go updateBaseTiles(jobs, btc, &done)
|
||||
}
|
||||
|
|
|
@ -54,9 +54,10 @@ type BaseTileCreator struct {
|
|||
func NewBaseTileCreator(
|
||||
client *RedisClient,
|
||||
colors *Colors,
|
||||
transparent bool,
|
||||
baseDir string,
|
||||
update bool) *BaseTileCreator {
|
||||
renderer := NewRenderer(tileWidth, tileHeight)
|
||||
renderer := NewRenderer(tileWidth, tileHeight, transparent)
|
||||
return &BaseTileCreator{
|
||||
client: client,
|
||||
colors: colors,
|
||||
|
@ -118,7 +119,7 @@ func (btc *BaseTileCreator) CreateTile(x, z int16, i, j int) error {
|
|||
|
||||
image := btc.renderer.CreateShadedImage(
|
||||
16, 16, (tileWidth-2)*16, (tileHeight-2)*16,
|
||||
btc.colors.Colors, color.RGBA{R: 0xff, G: 0xff, B: 0xff, A: 0xff})
|
||||
btc.colors, color.RGBA{R: 0xff, G: 0xff, B: 0xff, A: 0xff})
|
||||
|
||||
path := filepath.Join(btc.baseDir, strconv.Itoa(i), fmt.Sprintf("%d.png", j))
|
||||
|
||||
|
|
|
@ -115,8 +115,8 @@ func (colors *Colors) BlendColors(span *Span, col color.RGBA, pos int32) color.R
|
|||
}
|
||||
const scale = float32(1) / float32(100)
|
||||
for ; curr != nil; curr = curr.Next {
|
||||
// At least 20% attenuation + 5% extra for each depth meter.
|
||||
factor := float32(min(100, 20+(curr.To-curr.From)*5)) * scale
|
||||
// At least 35% attenuation + 5% extra for each depth meter.
|
||||
factor := float32(min(100, 35+(curr.To-curr.From)*5)) * scale
|
||||
col = BlendColor(colors.Colors[curr.Value], col, factor)
|
||||
}
|
||||
return col
|
||||
|
|
|
@ -27,6 +27,8 @@ type Renderer struct {
|
|||
RejectedBlocks int
|
||||
SolidBlocks int
|
||||
TransparentBlocks int
|
||||
spans *SpanPool
|
||||
tBuffer []*Span
|
||||
}
|
||||
|
||||
type YOrder struct {
|
||||
|
@ -122,19 +124,29 @@ func (yo *YOrder) Pop() (x interface{}) {
|
|||
return x
|
||||
}
|
||||
|
||||
func NewRenderer(width, height int) (renderer *Renderer) {
|
||||
func NewRenderer(width, height int, transparent bool) (renderer *Renderer) {
|
||||
dim := width * height
|
||||
pixSize := dim * 16 * 16
|
||||
yBuffer := make([]int32, pixSize)
|
||||
cBuffer := make([]int32, pixSize)
|
||||
yMin := make([]int32, dim)
|
||||
|
||||
var tBuffer []*Span
|
||||
var spans *SpanPool
|
||||
|
||||
if transparent {
|
||||
tBuffer = make([]*Span, pixSize)
|
||||
spans = NewSpanPool()
|
||||
}
|
||||
|
||||
renderer = &Renderer{
|
||||
width: width,
|
||||
height: height,
|
||||
yBuffer: yBuffer,
|
||||
cBuffer: cBuffer,
|
||||
yMin: yMin}
|
||||
yMin: yMin,
|
||||
tBuffer: tBuffer,
|
||||
spans: spans}
|
||||
|
||||
renderer.Reset()
|
||||
return
|
||||
|
@ -153,6 +165,15 @@ func (r *Renderer) Reset() {
|
|||
for i, n := 0, len(r.yMin); i < n; i++ {
|
||||
r.yMin[i] = math.MinInt32
|
||||
}
|
||||
|
||||
if r.tBuffer != nil {
|
||||
for i, t := range r.tBuffer {
|
||||
if t != nil {
|
||||
r.spans.FreeAll(t)
|
||||
r.tBuffer[i] = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Renderer) IsFilled() bool {
|
||||
|
@ -189,37 +210,64 @@ func (r *Renderer) RenderBlock(block *Block, colors *Colors) (err error) {
|
|||
return
|
||||
}
|
||||
|
||||
if db.Transparent {
|
||||
r.TransparentBlocks++
|
||||
} else {
|
||||
r.SolidBlocks++
|
||||
}
|
||||
|
||||
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 := yB[ofs]
|
||||
if currentY < blockY {
|
||||
for y := 15; y >= 0; y-- {
|
||||
if c, ok := db.Content(x, y, z); ok {
|
||||
r.cBuffer[ofs] = c
|
||||
currentY = blockY + int32(y)
|
||||
yB[ofs] = currentY
|
||||
break
|
||||
|
||||
if db.Transparent && r.tBuffer != nil {
|
||||
r.TransparentBlocks++
|
||||
|
||||
for z := 0; z < 16; z++ {
|
||||
for x := 0; x < 16; x++ {
|
||||
currentY := yB[ofs]
|
||||
if currentY < blockY {
|
||||
for y := 15; y >= 0; y-- {
|
||||
if c, ok := db.Content(x, y, z); ok {
|
||||
currentY = blockY + int32(y)
|
||||
|
||||
if colors.IsTransparent(c) {
|
||||
r.tBuffer[ofs] = r.spans.Insert(r.tBuffer[ofs], currentY, c)
|
||||
} else {
|
||||
r.cBuffer[ofs] = c
|
||||
yB[ofs] = currentY
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if currentY < yMin {
|
||||
yMin = currentY
|
||||
}
|
||||
ofs++
|
||||
}
|
||||
if currentY < yMin {
|
||||
yMin = currentY
|
||||
}
|
||||
ofs++
|
||||
ofs += w - 16
|
||||
}
|
||||
|
||||
} else {
|
||||
r.SolidBlocks++
|
||||
for z := 0; z < 16; z++ {
|
||||
for x := 0; x < 16; x++ {
|
||||
currentY := yB[ofs]
|
||||
if currentY < blockY {
|
||||
for y := 15; y >= 0; y-- {
|
||||
if c, ok := db.Content(x, y, z); ok {
|
||||
r.cBuffer[ofs] = c
|
||||
currentY = blockY + int32(y)
|
||||
yB[ofs] = currentY
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if currentY < yMin {
|
||||
yMin = currentY
|
||||
}
|
||||
ofs++
|
||||
}
|
||||
ofs += w - 16
|
||||
}
|
||||
ofs += w - 16
|
||||
}
|
||||
|
||||
r.yMin[pos] = yMin
|
||||
|
||||
return
|
||||
|
@ -349,13 +397,15 @@ func safeColor(x int32) uint8 {
|
|||
|
||||
func (r *Renderer) CreateShadedImage(
|
||||
xOfs, zOfs, width, height int,
|
||||
colors []color.RGBA, background color.RGBA) *image.RGBA {
|
||||
cols *Colors, background color.RGBA) *image.RGBA {
|
||||
|
||||
image := image.NewRGBA(image.Rect(0, 0, width, height))
|
||||
|
||||
pw := r.width << 4
|
||||
|
||||
ofs, numCols := zOfs*pw+xOfs, int32(len(colors))
|
||||
cs := cols.Colors
|
||||
|
||||
ofs, numCols := zOfs*pw+xOfs, int32(len(cs))
|
||||
|
||||
stride := pw - width
|
||||
|
||||
|
@ -365,42 +415,91 @@ func (r *Renderer) CreateShadedImage(
|
|||
|
||||
pix := image.Pix
|
||||
|
||||
for z := height - 1; z >= 0; z-- {
|
||||
for x := 0; x < width; x++ {
|
||||
colIdx := r.cBuffer[ofs]
|
||||
if colIdx < 0 || colIdx >= numCols {
|
||||
pix[iofs] = background.R
|
||||
pix[iofs+1] = background.G
|
||||
pix[iofs+2] = background.B
|
||||
pix[iofs+3] = 0xff
|
||||
} else {
|
||||
var y, y1, y2 int32
|
||||
y = r.yBuffer[ofs]
|
||||
if x == 0 {
|
||||
y1 = y
|
||||
if r.tBuffer != nil { // Fast path for transparent images.
|
||||
for z := height - 1; z >= 0; z-- {
|
||||
for x := 0; x < width; x++ {
|
||||
colIdx := r.cBuffer[ofs]
|
||||
if colIdx < 0 || colIdx >= numCols {
|
||||
pix[iofs] = background.R
|
||||
pix[iofs+1] = background.G
|
||||
pix[iofs+2] = background.B
|
||||
pix[iofs+3] = 0xff
|
||||
} else {
|
||||
y1 = r.yBuffer[ofs-1]
|
||||
var y, y1, y2 int32
|
||||
y = r.yBuffer[ofs]
|
||||
if x == 0 {
|
||||
y1 = y
|
||||
} else {
|
||||
y1 = r.yBuffer[ofs-1]
|
||||
}
|
||||
if z == 0 {
|
||||
y2 = y
|
||||
} else {
|
||||
y2 = r.yBuffer[ofs+pw]
|
||||
}
|
||||
d := ((y - y1) + (y - y2)) * 12
|
||||
if d > 36 {
|
||||
d = 36
|
||||
}
|
||||
col := cs[colIdx]
|
||||
col = color.RGBA{
|
||||
R: safeColor(int32(col.R) + d),
|
||||
G: safeColor(int32(col.G) + d),
|
||||
B: safeColor(int32(col.B) + d),
|
||||
A: 0xff}
|
||||
if r.tBuffer[ofs] != nil {
|
||||
col = cols.BlendColors(r.tBuffer[ofs], col, y)
|
||||
}
|
||||
pix[iofs] = col.R
|
||||
pix[iofs+1] = col.G
|
||||
pix[iofs+2] = col.B
|
||||
pix[iofs+3] = col.A
|
||||
}
|
||||
if z == 0 {
|
||||
y2 = y
|
||||
} else {
|
||||
y2 = r.yBuffer[ofs+pw]
|
||||
}
|
||||
d := ((y - y1) + (y - y2)) * 12
|
||||
if d > 36 {
|
||||
d = 36
|
||||
}
|
||||
col := colors[colIdx]
|
||||
pix[iofs] = safeColor(int32(col.R) + d)
|
||||
pix[iofs+1] = safeColor(int32(col.G) + d)
|
||||
pix[iofs+2] = safeColor(int32(col.B) + d)
|
||||
pix[iofs+3] = 0xff
|
||||
iofs += 4
|
||||
ofs++
|
||||
}
|
||||
iofs += 4
|
||||
ofs++
|
||||
ofs += stride
|
||||
iofs -= istride
|
||||
}
|
||||
|
||||
} else { // Solid images.
|
||||
for z := height - 1; z >= 0; z-- {
|
||||
for x := 0; x < width; x++ {
|
||||
colIdx := r.cBuffer[ofs]
|
||||
if colIdx < 0 || colIdx >= numCols {
|
||||
pix[iofs] = background.R
|
||||
pix[iofs+1] = background.G
|
||||
pix[iofs+2] = background.B
|
||||
pix[iofs+3] = 0xff
|
||||
} else {
|
||||
var y, y1, y2 int32
|
||||
y = r.yBuffer[ofs]
|
||||
if x == 0 {
|
||||
y1 = y
|
||||
} else {
|
||||
y1 = r.yBuffer[ofs-1]
|
||||
}
|
||||
if z == 0 {
|
||||
y2 = y
|
||||
} else {
|
||||
y2 = r.yBuffer[ofs+pw]
|
||||
}
|
||||
d := ((y - y1) + (y - y2)) * 12
|
||||
if d > 36 {
|
||||
d = 36
|
||||
}
|
||||
col := cs[colIdx]
|
||||
pix[iofs] = safeColor(int32(col.R) + d)
|
||||
pix[iofs+1] = safeColor(int32(col.G) + d)
|
||||
pix[iofs+2] = safeColor(int32(col.B) + d)
|
||||
pix[iofs+3] = 0xff
|
||||
}
|
||||
iofs += 4
|
||||
ofs++
|
||||
}
|
||||
ofs += stride
|
||||
iofs -= istride
|
||||
}
|
||||
ofs += stride
|
||||
iofs -= istride
|
||||
}
|
||||
return image
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user