0

added correct chunk boundary lighting

This commit is contained in:
Aaron Griffith
2010-09-27 19:59:41 -04:00
parent db62ad94ee
commit 8d145f2b58
2 changed files with 58 additions and 15 deletions

View File

@@ -21,6 +21,7 @@ import hashlib
import nbt
import textures
import world
"""
This module has routines related to rendering one particular chunk into an
@@ -86,12 +87,12 @@ def get_blocklight_array(level):
transparent_blocks = set([0, 6, 8, 9, 18, 20, 37, 38, 39, 40, 50, 51, 52, 53,
59, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 74, 75, 76, 77, 79, 83, 85])
def render_and_save(chunkfile, cachedir, cave=False):
def render_and_save(chunkfile, cachedir, worldobj, cave=False):
"""Used as the entry point for the multiprocessing workers (since processes
can't target bound methods) or to easily render and save one chunk
Returns the image file location"""
a = ChunkRenderer(chunkfile, cachedir)
a = ChunkRenderer(chunkfile, cachedir, worldobj)
try:
return a.render_and_save(cave)
except Exception, e:
@@ -108,7 +109,7 @@ def render_and_save(chunkfile, cachedir, cave=False):
raise Exception()
class ChunkRenderer(object):
def __init__(self, chunkfile, cachedir):
def __init__(self, chunkfile, cachedir, worldobj):
"""Make a new chunk renderer for the given chunkfile.
chunkfile should be a full path to the .dat file to process
cachedir is a directory to save the resulting chunk images to
@@ -117,7 +118,11 @@ class ChunkRenderer(object):
raise ValueError("Could not find chunkfile")
self.chunkfile = chunkfile
destdir, filename = os.path.split(self.chunkfile)
self.blockid = ".".join(filename.split(".")[1:3])
chunkcoords = filename.split(".")[1:3]
self.coords = map(world.base36decode, chunkcoords)
self.blockid = ".".join(chunkcoords)
self.world = worldobj
# Cachedir here is the base directory of the caches. We need to go 2
# levels deeper according to the chunk file. Get the last 2 components
@@ -241,9 +246,36 @@ class ChunkRenderer(object):
rendered, and blocks are drawn with a color tint depending on their
depth."""
blocks = self.blocks
# light data for the current chunk
skylight = get_skylight_array(self.level)
blocklight = get_blocklight_array(self.level)
# light data for the chunk to the lower left
chunk_path = self.world.get_chunk_path(self.coords[0] - 1, self.coords[1])
try:
chunk_data = get_lvldata(chunk_path)
left_skylight = get_skylight_array(chunk_data)
left_blocklight = get_blocklight_array(chunk_data)
del chunk_data
except IOError:
left_skylight = None
left_blocklight = None
# light data for the chunk to the lower right
chunk_path = self.world.get_chunk_path(self.coords[0], self.coords[1] + 1)
try:
chunk_data = get_lvldata(chunk_path)
right_skylight = get_skylight_array(chunk_data)
right_blocklight = get_blocklight_array(chunk_data)
del chunk_data
except IOError:
right_skylight = None
right_blocklight = None
# clean up namespace a bit
del chunk_path
if cave:
# Cave mode. Actually go through and 0 out all blocks that are not in a
# cave, so that it only renders caves.
@@ -347,6 +379,8 @@ class ChunkRenderer(object):
black_coeff = 0.0
if x != 0:
black_coeff = get_lighting_coefficient(skylight[x-1,y,z], blocklight[x-1,y,z])
elif left_skylight != None and left_blocklight != None:
black_coeff = get_lighting_coefficient(left_skylight[15,y,z], left_blocklight[15,y,z])
if x == 0 or (blocks[x-1,y,z] in transparent_blocks):
img.paste((0,0,0), (imgx, imgy), ImageEnhance.Brightness(facemasks[1]).enhance(black_coeff))
@@ -354,6 +388,8 @@ class ChunkRenderer(object):
black_coeff = 0.0
if y != 15:
black_coeff = get_lighting_coefficient(skylight[x,y+1,z], blocklight[x,y+1,z])
elif right_skylight != None and right_blocklight != None:
black_coeff = get_lighting_coefficient(right_skylight[x,0,z], right_blocklight[x,0,z])
if y == 15 or (blocks[x,y+1,z] in transparent_blocks):
img.paste((0,0,0), (imgx, imgy), ImageEnhance.Brightness(facemasks[2]).enhance(black_coeff))

View File

@@ -130,7 +130,18 @@ class WorldRenderer(object):
inclusion_set.add((col, row))
return inclusion_set
def get_chunk_path(self, chunkX, chunkY):
"""Returns the path to the chunk file at (chunkX, chunkY), if
it exists."""
chunkFile = "%s/%s/c.%s.%s.dat" % (base36encode(chunkX % 64),
base36encode(chunkY % 64),
base36encode(chunkX),
base36encode(chunkY))
return os.path.join(self.worlddir, chunkFile)
def findTrueSpawn(self):
"""Adds the true spawn location to self.POI. The spawn Y coordinate
is almost always the default of 64. Find the first air block above
@@ -147,13 +158,9 @@ class WorldRenderer(object):
chunkY = spawnZ/16
## The filename of this chunk
chunkFile = "%s/%s/c.%s.%s.dat" % (base36encode(chunkX % 64),
base36encode(chunkY % 64),
base36encode(chunkX),
base36encode(chunkY))
chunkFile = self.get_chunk_path(chunkX, chunkY)
data=nbt.load(os.path.join(self.worlddir, chunkFile))[1]
data=nbt.load(chunkFile)[1]
level = data['Level']
blockArray = numpy.frombuffer(level['Blocks'], dtype=numpy.uint8).reshape((16,16,128))
@@ -234,12 +241,12 @@ class WorldRenderer(object):
if inclusion_set and (col, row) not in inclusion_set:
# Skip rendering, just find where the existing image is
_, imgpath = chunk.ChunkRenderer(chunkfile,
self.cachedir).find_oldimage(False)
self.cachedir, self).find_oldimage(False)
if imgpath:
results[(col, row)] = imgpath
continue
result = chunk.render_and_save(chunkfile, self.cachedir, cave=self.caves)
result = chunk.render_and_save(chunkfile, self.cachedir, self, cave=self.caves)
results[(col, row)] = result
if i > 0:
if 1000 % i == 0 or i % 1000 == 0:
@@ -252,13 +259,13 @@ class WorldRenderer(object):
if inclusion_set and (col, row) not in inclusion_set:
# Skip rendering, just find where the existing image is
_, imgpath = chunk.ChunkRenderer(chunkfile,
self.cachedir).find_oldimage(False)
self.cachedir, self).find_oldimage(False)
if imgpath:
results[(col, row)] = imgpath
continue
result = pool.apply_async(chunk.render_and_save,
args=(chunkfile,self.cachedir),
args=(chunkfile,self.cachedir,self),
kwds=dict(cave=self.caves))
asyncresults.append((col, row, result))