0

Merge commit 'fenixin/dtt-c-render-water-redstone' into dtt-c-render

Changed 0b0000 constants into 0x00 equivalents.
This commit is contained in:
Aaron Griffith
2011-03-26 23:31:36 -04:00
2 changed files with 252 additions and 15 deletions

View File

@@ -74,7 +74,7 @@ is_transparent(unsigned char b) {
unsigned char
check_adjacent_blocks(RenderState *state, unsigned char blockid) {
check_adjacent_blocks(RenderState *state, int x,int y,int z, unsigned char blockid) {
/*
* Generates a pseudo ancillary data for blocks that depend of
* what are surrounded and don't have ancillary data. This
@@ -96,48 +96,48 @@ unsigned char
if (state->x == 15) { /* +x direction */
if (state->up_right_blocks != Py_None) { /* just in case we are in the end of the world */
if (getArrayByte3D(state->up_right_blocks, 0, state->y, state->z) == blockid) {
if (getArrayByte3D(state->up_right_blocks, 0, y, z) == blockid) {
pdata = pdata|(1 << 3);
}
}
} else {
if (getArrayByte3D(state->blocks, state->x + 1, state->y, state->z) == blockid) {
if (getArrayByte3D(state->blocks, x + 1, y, z) == blockid) {
pdata = pdata|(1 << 3);
}
}
if (state->y == 15) { /* +y direction*/
if (state->right_blocks != Py_None) {
if (getArrayByte3D(state->right_blocks, state->x, 0, state->z) == blockid) {
if (getArrayByte3D(state->right_blocks, x, 0, z) == blockid) {
pdata = pdata|(1 << 2);
}
}
} else {
if (getArrayByte3D(state->blocks, state->x, state->y + 1, state->z) == blockid) {
if (getArrayByte3D(state->blocks, x, y + 1, z) == blockid) {
pdata = pdata|(1 << 2);
}
}
if (state->x == 0) { /* -x direction*/
if (state->left_blocks != Py_None) {
if (getArrayByte3D(state->left_blocks, 15, state->y, state->z) == blockid) {
if (getArrayByte3D(state->left_blocks, 15, y, z) == blockid) {
pdata = pdata|(1 << 1);
}
}
} else {
if (getArrayByte3D(state->blocks, state->x - 1, state->y, state->z) == blockid) {
if (getArrayByte3D(state->blocks, x - 1, y, z) == blockid) {
pdata = pdata|(1 << 1);
}
}
if (state->y == 0) { /* -y direction */
if (state->up_left_blocks != Py_None) {
if (getArrayByte3D(state->up_left_blocks, state->x, 15, state->z) == blockid) {
if (getArrayByte3D(state->up_left_blocks, x, 15, z) == blockid) {
pdata = pdata|(1 << 0);
}
}
} else {
if (getArrayByte3D(state->blocks, state->x, state->y - 1, state->z) == blockid) {
if (getArrayByte3D(state->blocks, x, y - 1, z) == blockid) {
pdata = pdata|(1 << 0);
}
}
@@ -147,15 +147,69 @@ unsigned char
unsigned char
generate_pseudo_data(RenderState *state) {
generate_pseudo_data(RenderState *state, unsigned char ancilData) {
/*
* Generates a fake ancillary data for blocks that are drawn
* depending on what are surrounded.
*/
int x = state->x, y = state->y, z = state->z;
unsigned char data = 0;
if (state->block == 85) { /* fences */
return check_adjacent_blocks(state, state->block);
if (state->block == 9) { /* water */
/* an aditional bit for top is added to the 4 bits of check_adjacent_blocks */
if ((ancilData == 0) || (ancilData >= 10)) { /* static water, only top, and unkown ancildata values */
data = 16;
return data; /* = 0b10000 */
} else if ((ancilData > 0) && (ancilData < 8)) { /* flowing water */
data = (check_adjacent_blocks(state, x, y, z, state->block) ^ 0x0f) | 0x10;
return data;
} else if ((ancilData == 8) || (ancilData == 9)) { /* falling water */
data = (check_adjacent_blocks(state, x, y, z, state->block) ^ 0x0f);
return data;
}
} else if (state->block == 85) { /* fences */
return check_adjacent_blocks(state, x, y, z, state->block);
} else if (state->block == 55) { /* redstone */
/* three addiotional bit are added, one for on/off state, and
* another two for going-up redstone wire in the same block
* (connection with the level z+1) */
unsigned char above_level_data = 0, same_level_data = 0, below_level_data = 0, possibly_connected = 0, final_data = 0;
/* check for air in z+1, no air = no connection with upper level */
if ((z != 127) && (getArrayByte3D(state->left_blocks, x, y, z) == 0)) {
above_level_data = check_adjacent_blocks(state, x, y, z + 1, state->block);
} /* else above_level_data = 0 */
/* check connection with same level */
same_level_data = check_adjacent_blocks(state, x, y, z, 55);
/* check the posibility of connection with z-1 level, check for air */
possibly_connected = check_adjacent_blocks(state, x, y, z, 0);
/* check connection with z-1 level */
if (z != 0) {
below_level_data = check_adjacent_blocks(state, x, y, z - 1, state->block);
} /* else below_level_data = 0 */
final_data = above_level_data | same_level_data | (below_level_data & possibly_connected);
/* add the three bits */
if (ancilData > 0) { /* powered redstone wire */
final_data = final_data | 0x40;
}
if ((above_level_data & 0x01)) { /* draw top left going up redstonewire */
final_data = final_data | 0x20;
}
if ((above_level_data & 0x08)) { /* draw top right going up redstonewire */
final_data = final_data | 0x10;
}
return final_data;
}
return 0;
}
@@ -275,8 +329,8 @@ chunk_render(PyObject *self, PyObject *args) {
PyObject *tmp;
unsigned char ancilData = getArrayByte3D(blockdata_expanded, state.x, state.y, state.z);
if (state.block == 85) {
ancilData = generate_pseudo_data(&state);
if ((state.block == 85) || (state.block == 9) || (state.block == 55)) {
ancilData = generate_pseudo_data(&state, ancilData);
}
tmp = PyTuple_New(2);

View File

@@ -265,6 +265,79 @@ def _build_block(top, side, blockID=None):
return img
def _build_full_block(top, side1, side2, side3, side4, bottom=None, blockID=None):
"""From a top texture, a bottom texture and 4 different side textures,
build a full block with four differnts faces. All images should be 16x16
image objects. Returns a 24x24 image. Can be used to render any block.
side1 is in the -y face of the cube (top left)
side2 is in the +x (top right)
side3 is in the -x (bottom left)
side4 is in the +y (bottom right)
A non transparent block uses top, side 3 and side 4
"""
img = Image.new("RGBA", (24,24), (38,92,255,0))
# first back sides
if side1 != None :
side1 = transform_image_side(side1, blockID)
side1 = side1.transpose(Image.FLIP_TOP_BOTTOM)
# Darken this side.
sidealpha = side1.split()[3]
side1 = ImageEnhance.Brightness(side1).enhance(0.9)
side1.putalpha(sidealpha)
composite.alpha_over(img, side1, (0,0), side1)
if side2 != None :
side2 = transform_image_side(side2, blockID)
side2 = side2.transpose(Image.FLIP_LEFT_RIGHT)
side2 = side2.transpose(Image.FLIP_TOP_BOTTOM)
# Darken this side.
sidealpha2 = side2.split()[3]
side2 = ImageEnhance.Brightness(side2).enhance(0.8)
side2.putalpha(sidealpha2)
composite.alpha_over(img, side2, (12,0), side2)
if bottom != None :
bottom = transform_image(bottom, blockID)
composite.alpha_over(img, bottom, (0,12), top)
if top != None :
top = transform_image(top, blockID)
composite.alpha_over(img, top, (0,0), top)
# front sides
if side3 != None :
side3 = transform_image_side(side3, blockID)
# Darken this side
sidealpha = side3.split()[3]
side3 = ImageEnhance.Brightness(side3).enhance(0.9)
side3.putalpha(sidealpha)
composite.alpha_over(img, side3, (0,6), side3)
if side4 != None :
side4 = transform_image_side(side4, blockID)
side4 = side4.transpose(Image.FLIP_LEFT_RIGHT)
# Darken this side
sidealpha = side4.split()[3]
side4 = ImageEnhance.Brightness(side4).enhance(0.8)
side4.putalpha(sidealpha)
composite.alpha_over(img, side4, (12,6), side4)
return img
def _build_blockimages():
"""Returns a mapping from blockid to an image of that block in perspective
The values of the mapping are actually (image in RGB mode, alpha channel).
@@ -801,6 +874,114 @@ def generate_special_texture(blockID, data):
img = _build_block(top, side, blockID)
return (img.convert("RGB"), img.split()[3])
if blockID == 9: # spring water, flowing water and waterfall water
watertexture = _load_image("water.png")
if (data & 0b10000) == 16:
top = watertexture
else: top = None
if (data & 0b0001) == 1:
side1 = watertexture # top left
else: side1 = None
if (data & 0b1000) == 8:
side2 = watertexture # top right
else: side2 = None
if (data & 0b0010) == 2:
side3 = watertexture # bottom left
else: side3 = None
if (data & 0b0100) == 4:
side4 = watertexture # bottom right
else: side4 = None
img = _build_full_block(top,side1,side2,side3,side4)
return (img.convert("RGB"),img.split()[3])
if blockID == 55: # redstone wire
if data & 0b1000000 == 64: # powered redstone wire
redstone_wire_t = terrain_images[165]
redstone_wire_t = tintTexture(redstone_wire_t,(255,0,0))
redstone_cross_t = terrain_images[164]
redstone_cross_t = tintTexture(redstone_cross_t,(255,0,0))
else: # unpowered redstone wire
redstone_wire_t = terrain_images[165]
redstone_wire_t = tintTexture(redstone_wire_t,(48,0,0))
redstone_cross_t = terrain_images[164]
redstone_cross_t = tintTexture(redstone_cross_t,(48,0,0))
# generate an image per redstone direction
branch_top_left = redstone_cross_t.copy()
ImageDraw.Draw(branch_top_left).rectangle((0,0,4,15),outline=(0,0,0,0),fill=(0,0,0,0))
ImageDraw.Draw(branch_top_left).rectangle((11,0,15,15),outline=(0,0,0,0),fill=(0,0,0,0))
ImageDraw.Draw(branch_top_left).rectangle((0,11,15,15),outline=(0,0,0,0),fill=(0,0,0,0))
branch_top_right = redstone_cross_t.copy()
ImageDraw.Draw(branch_top_right).rectangle((0,0,15,4),outline=(0,0,0,0),fill=(0,0,0,0))
ImageDraw.Draw(branch_top_right).rectangle((0,0,4,15),outline=(0,0,0,0),fill=(0,0,0,0))
ImageDraw.Draw(branch_top_right).rectangle((0,11,15,15),outline=(0,0,0,0),fill=(0,0,0,0))
branch_bottom_right = redstone_cross_t.copy()
ImageDraw.Draw(branch_bottom_right).rectangle((0,0,15,4),outline=(0,0,0,0),fill=(0,0,0,0))
ImageDraw.Draw(branch_bottom_right).rectangle((0,0,4,15),outline=(0,0,0,0),fill=(0,0,0,0))
ImageDraw.Draw(branch_bottom_right).rectangle((11,0,15,15),outline=(0,0,0,0),fill=(0,0,0,0))
branch_bottom_left = redstone_cross_t.copy()
ImageDraw.Draw(branch_bottom_left).rectangle((0,0,15,4),outline=(0,0,0,0),fill=(0,0,0,0))
ImageDraw.Draw(branch_bottom_left).rectangle((11,0,15,15),outline=(0,0,0,0),fill=(0,0,0,0))
ImageDraw.Draw(branch_bottom_left).rectangle((0,11,15,15),outline=(0,0,0,0),fill=(0,0,0,0))
# generate the bottom texture
if data & 0b111111 == 0:
bottom = redstone_cross_t.copy()
elif data & 0b1111 == 10: #= 0b1010 redstone wire in the x direction
bottom = redstone_wire_t.copy()
elif data & 0b1111 == 5: #= 0b0101 redstone wire in the y direction
bottom = redstone_wire_t.copy().rotate(90)
else:
bottom = Image.new("RGBA", (16,16), (38,92,255,0))
if (data & 0b0001) == 1:
composite.alpha_over(bottom,branch_top_left)
if (data & 0b1000) == 8:
composite.alpha_over(bottom,branch_top_right)
if (data & 0b0010) == 2:
composite.alpha_over(bottom,branch_bottom_left)
if (data & 0b0100) == 4:
composite.alpha_over(bottom,branch_bottom_right)
# check for going up redstone wire
if data & 0b100000 == 32:
side1 = redstone_wire_t.rotate(90)
else:
side1 = None
if data & 0b010000 == 16:
side2 = redstone_wire_t.rotate(90)
else:
side2 = None
img = _build_full_block(None,side1,side2,None,None,bottom)
return (img.convert("RGB"),img.split()[3])
return None
def tintTexture(im, c):
@@ -896,7 +1077,7 @@ def getBiomeData(worlddir, chunkX, chunkY):
# This set holds block ids that require special pre-computing. These are typically
# things that require ancillary data to render properly (i.e. ladder plus orientation)
special_blocks = set([66,59,61,62, 65,64,71,91,86,2,18,85,17,23,35,51,43,44])
special_blocks = set([66,59,61,62, 65,64,71,91,86,2,18,85,17,23,35,51,43,44,9,55])
# this is a map of special blockIDs to a list of all
# possible values for ancillary data that it might have.
@@ -917,6 +1098,8 @@ special_map[35] = range(16) # wool, colored and white
special_map[51] = range(16) # fire
special_map[43] = range(4) # stone, sandstone, wooden and cobblestone double-slab
special_map[44] = range(4) # stone, sandstone, wooden and cobblestone slab
special_map[9] = range(32) # water: spring,flowing, waterfall, and others (unknown) ancildata values.
special_map[55] = range(128) # redstone wire
# apparently pumpkins and jack-o-lanterns have ancillary data, but it's unknown
# what that data represents. For now, assume that the range for data is 0 to 5