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 nbt
import textures import textures
import world
""" """
This module has routines related to rendering one particular chunk into an 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, 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]) 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 """Used as the entry point for the multiprocessing workers (since processes
can't target bound methods) or to easily render and save one chunk can't target bound methods) or to easily render and save one chunk
Returns the image file location""" Returns the image file location"""
a = ChunkRenderer(chunkfile, cachedir) a = ChunkRenderer(chunkfile, cachedir, worldobj)
try: try:
return a.render_and_save(cave) return a.render_and_save(cave)
except Exception, e: except Exception, e:
@@ -108,7 +109,7 @@ def render_and_save(chunkfile, cachedir, cave=False):
raise Exception() raise Exception()
class ChunkRenderer(object): class ChunkRenderer(object):
def __init__(self, chunkfile, cachedir): def __init__(self, chunkfile, cachedir, worldobj):
"""Make a new chunk renderer for the given chunkfile. """Make a new chunk renderer for the given chunkfile.
chunkfile should be a full path to the .dat file to process chunkfile should be a full path to the .dat file to process
cachedir is a directory to save the resulting chunk images to cachedir is a directory to save the resulting chunk images to
@@ -117,7 +118,11 @@ class ChunkRenderer(object):
raise ValueError("Could not find chunkfile") raise ValueError("Could not find chunkfile")
self.chunkfile = chunkfile self.chunkfile = chunkfile
destdir, filename = os.path.split(self.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 # 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 # 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 rendered, and blocks are drawn with a color tint depending on their
depth.""" depth."""
blocks = self.blocks blocks = self.blocks
# light data for the current chunk
skylight = get_skylight_array(self.level) skylight = get_skylight_array(self.level)
blocklight = get_blocklight_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: if cave:
# Cave mode. Actually go through and 0 out all blocks that are not in a # Cave mode. Actually go through and 0 out all blocks that are not in a
# cave, so that it only renders caves. # cave, so that it only renders caves.
@@ -347,6 +379,8 @@ class ChunkRenderer(object):
black_coeff = 0.0 black_coeff = 0.0
if x != 0: if x != 0:
black_coeff = get_lighting_coefficient(skylight[x-1,y,z], blocklight[x-1,y,z]) 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): 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)) 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 black_coeff = 0.0
if y != 15: if y != 15:
black_coeff = get_lighting_coefficient(skylight[x,y+1,z], blocklight[x,y+1,z]) 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): 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)) img.paste((0,0,0), (imgx, imgy), ImageEnhance.Brightness(facemasks[2]).enhance(black_coeff))

View File

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