0

modified tileset.py for the new Anvil format

This commit is contained in:
Andrew Brown
2012-02-19 00:04:26 -05:00
parent 293e16e17f
commit 4c21fb2e05
4 changed files with 117 additions and 88 deletions

View File

@@ -15,7 +15,7 @@
version="1.1"
inkscape:version="0.48.1 r9760"
sodipodi:docname="chunk_perspective.svg"
inkscape:export-filename="/home/andrew/mc/overviewer/docs/design/cuberenderimgs/chunk_perspective.png"
inkscape:export-filename="/home/andrew/mc/overviewer/anvil/docs/design/cuberenderimgs/chunk_perspective.png"
inkscape:export-xdpi="90.015251"
inkscape:export-ydpi="90.015251">
<defs
@@ -27,9 +27,9 @@
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.5"
inkscape:cx="74.237364"
inkscape:cy="-54.873869"
inkscape:zoom="2"
inkscape:cx="167.0549"
inkscape:cy="-24.751909"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
@@ -61,7 +61,7 @@
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>

Before

Width:  |  Height:  |  Size: 142 KiB

After

Width:  |  Height:  |  Size: 142 KiB

View File

@@ -24,10 +24,11 @@ import time
import errno
import stat
from collections import namedtuple
from itertools import product, izip
from PIL import Image
from .util import iterate_base4, convert_coords, unconvert_coords, get_tiles_by_chunk
from .util import iterate_base4, convert_coords, unconvert_coords, roundrobin
from .optimizeimages import optimize_image
import c_overviewer
@@ -761,7 +762,7 @@ class TileSet(object):
# Calculate which chunks are relevant to this tile
# This is a list of (col, row, chunkx, chunkz, chunk_mtime)
chunks = list(self._get_chunks_for_tile(tile))
chunks = list(get_chunks_by_tile(tile, self.regionset))
if not chunks:
# No chunks were found in this tile
@@ -798,32 +799,33 @@ class TileSet(object):
# col colstart will get drawn on the image starting at x coordinates -(384/2)
# row rowstart will get drawn on the image starting at y coordinates -(192/2)
max_chunk_mtime = 0
for col, row, chunkx, chunkz, chunk_mtime in chunks:
for col, row, chunkx, chunky, chunkz, chunk_mtime in chunks:
xpos = -192 + (col-colstart)*192
ypos = -96 + (row-rowstart)*96
ypos = -96 + (row-rowstart)*96 + chunky*192
if chunk_mtime > max_chunk_mtime:
max_chunk_mtime = chunk_mtime
# draw the chunk!
c_overviewer.render_loop(self.regionset, chunkx, chunkz, tileimg,
xpos, ypos, self.options['rendermode'], self.textures)
c_overviewer.render_loop(self.regionset, chunkx, chunky, chunkz,
tileimg, xpos, ypos, self.options['rendermode'],
self.textures)
if 0:
# Draw the outline of the top of the chunk
import ImageDraw
draw = ImageDraw.Draw(tileimg)
# Draw top outline
draw.line([(192,0), (384,96)], fill='red')
draw.line([(192,0), (0,96)], fill='red')
draw.line([(0,96), (192,192)], fill='red')
draw.line([(384,96), (192,192)], fill='red')
# Draw side outline
draw.line([(0,96),(0,96+1536)], fill='red')
draw.line([(384,96),(384,96+1536)], fill='red')
# Which chunk this is:
draw.text((96,48), "C: %s,%s" % (chunkx, chunkz), fill='red')
draw.text((96,96), "c,r: %s,%s" % (col, row), fill='red')
## Semi-handy routine for debugging the drawing routine
## Draw the outline of the top of the chunk
#import ImageDraw
#draw = ImageDraw.Draw(tileimg)
## Draw top outline
#draw.line([(192,0), (384,96)], fill='red')
#draw.line([(192,0), (0,96)], fill='red')
#draw.line([(0,96), (192,192)], fill='red')
#draw.line([(384,96), (192,192)], fill='red')
## Draw side outline
#draw.line([(0,96),(0,96+192)], fill='red')
#draw.line([(384,96),(384,96+192)], fill='red')
## Which chunk this is:
#draw.text((96,48), "C: %s,%s" % (chunkx, chunkz), fill='red')
#draw.text((96,96), "c,r: %s,%s" % (col, row), fill='red')
# Save them
if self.imgextension == 'jpg':
@@ -836,40 +838,6 @@ class TileSet(object):
os.utime(imgpath, (max_chunk_mtime, max_chunk_mtime))
def _get_chunks_for_tile(self, tile):
"""Get chunks that are relevant to the given render-tile
Returns an iterator over chunks tuples where each item is
(col, row, chunkx, chunkz, mtime)
"""
chunklist = []
# Chunks that are relevant to this tile: the 8 chunks directly in this
# tile, and the chunks from the previous 16 rows
rowstart = tile.row
rowend = rowstart+4
colstart = tile.col
colend = colstart+2
# Start 16 rows up from the actual tile's row, since chunks are that tall.
# Also, every other tile doesn't exist due to how chunks are arranged. See
# http://docs.overviewer.org/en/latest/design/designdoc/#chunk-addressing
for row, col in itertools.product(
xrange(rowstart-16, rowend+1),
xrange(colstart, colend+1)
):
if row % 2 != col % 2:
continue
chunkx, chunkz = unconvert_coords(col, row)
# Query for info on the chunk at chunkx, chunkz
mtime = self.regionset.get_chunk_mtime(chunkx, chunkz)
if mtime:
# The chunk exists
yield (col, row, chunkx, chunkz, mtime)
def _iterate_and_check_tiles(self, path):
"""A generator function over all tiles that need rendering in the
subtree identified by path. This yields, in order, all tiles that need
@@ -904,7 +872,7 @@ class TileSet(object):
raise
tile_mtime = 0
max_chunk_mtime = max(c[4] for c in self._get_chunks_for_tile(tileobj))
max_chunk_mtime = max(c[5] for c in get_chunks_by_tile(tileobj, self.regionset))
if tile_mtime > 120 + max_chunk_mtime:
# If a tile has been modified more recently than any of its
@@ -1005,6 +973,93 @@ def get_dirdepth(outputdir):
return depth
######################
# The following two functions define the mapping from chunks to tiles and back.
# The mapping from chunks to tiles (get_tiles_by_chunk()) is used during the
# chunk scan to determine which tiles need updating, while the mapping from a
# tile to chunks (get_chunks_by_tile()) is used by the tile rendering routines
# to get which chunks are needed.
def get_tiles_by_chunk(chunkcol, chunkrow):
"""For the given chunk, returns an iterator over Render Tiles that this
chunk touches. Iterates over (tilecol, tilerow)
"""
# find tile coordinates. Remember tiles are identified by the
# address of the chunk in their upper left corner.
tilecol = chunkcol - chunkcol % 2
tilerow = chunkrow - chunkrow % 4
# If this chunk is in an /even/ column, then it spans two tiles.
if chunkcol % 2 == 0:
colrange = (tilecol-2, tilecol)
else:
colrange = (tilecol,)
# If this chunk is in a row divisible by 4, then it touches the
# tile above it as well. Also touches the next 4 tiles down (16
# rows)
if chunkrow % 4 == 0:
rowrange = xrange(tilerow-4, tilerow+32+1, 4)
else:
rowrange = xrange(tilerow, tilerow+32+1, 4)
return product(colrange, rowrange)
def get_chunks_by_tile(tile, regionset):
"""Get chunk sections that are relevant to the given render-tile. Only
returns chunk sections that are in chunks that actually exist according to
the given regionset object. (Does not check to see if the chunk section
itself within the chunk exists)
This function is expected to return the chunk sections in the correct order
for rendering, i.e. back to front.
Returns an iterator over chunks tuples where each item is
(col, row, chunkx, chunky, chunkz, mtime)
"""
# This is not a documented usage of this function and is used only for
# debugging
if regionset is None:
get_mtime = lambda x,y: True
else:
get_mtime = regionset.get_chunk_mtime
# Each tile has two even columns and an odd column of chunks.
# First do the odd. For each chunk in the tile's odd column the tile
# "passes through" three chunk sections.
oddcol_sections = []
for i, y in enumerate(reversed(xrange(16))):
for row in xrange(tile.row + 3 - i*2, tile.row - 2 - i*2, -2):
oddcol_sections.append((tile.col+1, row, y))
evencol_sections = []
for i, y in enumerate(reversed(xrange(16))):
for row in xrange(tile.row + 4 - i*2, tile.row - 3 - i*2, -2):
evencol_sections.append((tile.col+2, row, y))
evencol_sections.append((tile.col, row, y))
eveniter = reversed(evencol_sections)
odditer = reversed(oddcol_sections)
# There are 4 rows of chunk sections per Y value on even columns, but 3
# rows on odd columns. This iteration order yields them in back-to-front
# order appropriate for rendering
for col, row, y in roundrobin((
eveniter,eveniter,
odditer,
eveniter,eveniter,
odditer,
eveniter,eveniter,
odditer,
eveniter,eveniter,
)):
chunkx, chunkz = unconvert_coords(col, row)
mtime = get_mtime(chunkx, chunkz)
if mtime:
yield (col, row, chunkx, y, chunkz, mtime)
class RendertileSet(object):
"""This object holds a set of render-tiles using a quadtree data structure.
It is typically used to hold tiles that need rendering. This implementation

View File

@@ -152,32 +152,6 @@ def unconvert_coords(col, row):
# col - row = chunkx + chunkx => (col - row)/2 = chunkx
return ((col - row) / 2, (col + row) / 2)
def get_tiles_by_chunk(chunkcol, chunkrow):
"""For the given chunk, returns an iterator over Render Tiles that this
chunk touches. Iterates over (tilecol, tilerow)
"""
# find tile coordinates. Remember tiles are identified by the
# address of the chunk in their upper left corner.
tilecol = chunkcol - chunkcol % 2
tilerow = chunkrow - chunkrow % 4
# If this chunk is in an /even/ column, then it spans two tiles.
if chunkcol % 2 == 0:
colrange = (tilecol-2, tilecol)
else:
colrange = (tilecol,)
# If this chunk is in a row divisible by 4, then it touches the
# tile above it as well. Also touches the next 4 tiles down (16
# rows)
if chunkrow % 4 == 0:
rowrange = xrange(tilerow-4, tilerow+16+1, 4)
else:
rowrange = xrange(tilerow, tilerow+16+1, 4)
return product(colrange, rowrange)
# Logging related classes are below
# Some cool code for colored logging:

View File

@@ -122,7 +122,7 @@ def get_tile_set(chunks):
col, row = util.convert_coords(chunkx, chunkz)
for tilec, tiler in util.get_tiles_by_chunk(col, row):
for tilec, tiler in tileset.get_tiles_by_chunk(col, row):
tile = tileset.RenderTile.compute_path(tilec, tiler, 3)
tile_set[tile.path] = max(tile_set[tile.path], chunkmtime)