diff --git a/overviewer_core/src/rendermode-normal.c b/overviewer_core/src/rendermode-normal.c index 5f71982..d03feb2 100644 --- a/overviewer_core/src/rendermode-normal.c +++ b/overviewer_core/src/rendermode-normal.c @@ -44,6 +44,9 @@ rendermode_normal_start(void *data, RenderState *state, PyObject *options) { self->black_color = PyObject_GetAttrString(state->chunk, "black_color"); self->white_color = PyObject_GetAttrString(state->chunk, "white_color"); } + + /* biome-compliant grass mask (includes sides!) */ + self->grass_texture = PyObject_GetAttrString(state->textures, "biome_grass_texture"); chunk_x_py = PyObject_GetAttrString(state->self, "chunkX"); chunk_y_py = PyObject_GetAttrString(state->self, "chunkY"); @@ -68,45 +71,21 @@ rendermode_normal_start(void *data, RenderState *state, PyObject *options) { Py_DECREF(world); if (PyObject_IsTrue(use_biomes)) { - PyObject *facemasks_py; - self->biome_data = PyObject_CallMethod(state->textures, "getBiomeData", "OOO", worlddir, chunk_x_py, chunk_y_py); if (self->biome_data == Py_None) { + Py_DECREF(self->biome_data); self->biome_data = NULL; self->foliagecolor = NULL; self->grasscolor = NULL; - - self->leaf_texture = NULL; - self->grass_texture = NULL; - self->tall_grass_texture = NULL; - self->facemask_top = NULL; } else { - self->foliagecolor = PyObject_GetAttrString(state->textures, "foliagecolor"); self->grasscolor = PyObject_GetAttrString(state->textures, "grasscolor"); - - self->leaf_texture = PyObject_GetAttrString(state->textures, "biome_leaf_texture"); - self->grass_texture = PyObject_GetAttrString(state->textures, "biome_grass_texture"); - self->tall_grass_texture = PyObject_GetAttrString(state->textures, "biome_tall_grass_texture"); - self->tall_fern_texture = PyObject_GetAttrString(state->textures, "biome_tall_fern_texture"); - - facemasks_py = PyObject_GetAttrString(state->chunk, "facemasks"); - /* borrowed reference, needs to be incref'd if we keep it */ - self->facemask_top = PyTuple_GetItem(facemasks_py, 0); - Py_INCREF(self->facemask_top); - Py_DECREF(facemasks_py); } } else { self->biome_data = NULL; self->foliagecolor = NULL; self->grasscolor = NULL; - - self->leaf_texture = NULL; - self->grass_texture = NULL; - self->tall_grass_texture = NULL; - self->tall_fern_texture = NULL; - self->facemask_top = NULL; } Py_DECREF(use_biomes); @@ -124,11 +103,7 @@ rendermode_normal_finish(void *data, RenderState *state) { Py_XDECREF(self->biome_data); Py_XDECREF(self->foliagecolor); Py_XDECREF(self->grasscolor); - Py_XDECREF(self->leaf_texture); Py_XDECREF(self->grass_texture); - Py_XDECREF(self->tall_grass_texture); - Py_XDECREF(self->tall_fern_texture); - Py_XDECREF(self->facemask_top); Py_XDECREF(self->black_color); Py_XDECREF(self->white_color); } @@ -162,77 +137,88 @@ rendermode_normal_hidden(void *data, RenderState *state, int x, int y, int z) { static void rendermode_normal_draw(void *data, RenderState *state, PyObject *src, PyObject *mask, PyObject *mask_light) { RenderModeNormal *self = (RenderModeNormal *)data; - unsigned char data_byte; - - /* first, check to see if we should use biome-compatible src, mask */ - if (self->biome_data) { - if (state->block == 18) { - src = mask = self->leaf_texture; - } else if (state->block == 31) { - data_byte = getArrayByte3D(state->blockdata_expanded, state->x, state->y, state->z); - if (data_byte == 1) { - src = mask = self->tall_grass_texture; - } else if (data_byte == 2) { - src = mask = self->tall_fern_texture; - } - } - } - + /* draw the block! */ alpha_over(state->img, src, mask, state->imgx, state->imgy, 0, 0); - if (self->biome_data) { + /* check for biome-compatible blocks + * + * NOTES for maintainers: + * + * To add a biome-compatible block, add an OR'd condition to this + * following if block, a case to the first switch statement to handle when + * biome info IS available, and another case to the second switch + * statement for when biome info ISN'T available. + * + * Make sure that in textures.py, the generated textures are the + * biome-compliant ones! The tinting is now all done here. + */ + if (/* grass, but not snowgrass */ + (state->block == 2 && !(state->z < 127 && getArrayByte3D(state->blocks, state->x, state->y, state->z+1) == 78)) || + /* leaves */ + state->block == 18 || + /* tallgrass, but not dead shrubs */ + (state->block == 31 && getArrayByte3D(state->blockdata_expanded, state->x, state->y, state->z) != 0) || + /* vines */ + state->block == 106) + { /* do the biome stuff! */ - unsigned int index; - PyObject *color = NULL, *facemask = NULL; + PyObject *facemask = mask; unsigned char r, g, b; - index = ((self->chunk_y * 16) + state->y) * 16 * 32 + (self->chunk_x * 16) + state->x; - index = big_endian_ushort(getArrayShort1D(self->biome_data, index)); - - switch (state->block) { - case 2: - /* grass -- skip for snowgrass */ - if (state->z < 127 && getArrayByte3D(state->blocks, state->x, state->y, state->z+1) == 78) - break; - color = PySequence_GetItem(self->grasscolor, index); + if (state->block == 2) { + /* grass needs a special facemask */ facemask = self->grass_texture; - alpha_over(state->img, self->grass_texture, self->grass_texture, state->imgx, state->imgy, 0, 0); - break; - case 18: - /* leaves */ - color = PySequence_GetItem(self->foliagecolor, index); - facemask = mask; - break; - case 31: - /* tall grass */ - if ( getArrayByte3D(state->blockdata_expanded, state->x, state->y, state->z) != 0 ) - { /* do not tint dead shrubs */ - color = PySequence_GetItem(self->grasscolor, index); - facemask = mask; - break; - } - break; - case 106: - /* vines */ - color = PySequence_GetItem(self->grasscolor, index); - facemask = mask; - break; - default: - break; - }; - - if (color) - { - /* we've got work to do */ - - r = PyInt_AsLong(PyTuple_GET_ITEM(color, 0)); - g = PyInt_AsLong(PyTuple_GET_ITEM(color, 1)); - b = PyInt_AsLong(PyTuple_GET_ITEM(color, 2)); - Py_DECREF(color); - - tint_with_mask(state->img, r, g, b, 255, facemask, state->imgx, state->imgy, 0, 0); } + + if (self->biome_data) { + /* we have data, so use it! */ + unsigned int index; + PyObject *color = NULL; + + index = ((self->chunk_y * 16) + state->y) * 16 * 32 + (self->chunk_x * 16) + state->x; + index = big_endian_ushort(getArrayShort1D(self->biome_data, index)); + + switch (state->block) { + case 2: + /* grass */ + color = PySequence_GetItem(self->grasscolor, index); + break; + case 18: + /* leaves */ + color = PySequence_GetItem(self->foliagecolor, index); + break; + case 31: + /* tall grass */ + color = PySequence_GetItem(self->grasscolor, index); + break; + case 106: + /* vines */ + color = PySequence_GetItem(self->grasscolor, index); + break; + default: + break; + }; + + if (color) + { + /* we've got work to do */ + + r = PyInt_AsLong(PyTuple_GET_ITEM(color, 0)); + g = PyInt_AsLong(PyTuple_GET_ITEM(color, 1)); + b = PyInt_AsLong(PyTuple_GET_ITEM(color, 2)); + Py_DECREF(color); + } + } else { + /* manual tinting required */ + + /* FIXME */ + r = 255; + g = 255; + b = 255; + } + + tint_with_mask(state->img, r, g, b, 255, facemask, state->imgx, state->imgy, 0, 0); } if (self->height_fading) { diff --git a/overviewer_core/src/rendermodes.h b/overviewer_core/src/rendermodes.h index 310bf0e..0825802 100644 --- a/overviewer_core/src/rendermodes.h +++ b/overviewer_core/src/rendermodes.h @@ -127,9 +127,7 @@ typedef struct { /* grasscolor and foliagecolor lookup tables */ PyObject *grasscolor, *foliagecolor; /* biome-compatible grass/leaf textures */ - PyObject *grass_texture, *leaf_texture, *tall_grass_texture, *tall_fern_texture; - /* top facemask for grass biome tinting */ - PyObject *facemask_top; + PyObject *grass_texture; /* black and white colors for height fading */ PyObject *black_color, *white_color; diff --git a/overviewer_core/textures.py b/overviewer_core/textures.py index 6889792..e670186 100644 --- a/overviewer_core/textures.py +++ b/overviewer_core/textures.py @@ -532,8 +532,8 @@ def generate_special_texture(blockID, data): side_img = terrain_images[68] img = _build_block(terrain_images[0], side_img, 2) if not data & 0x10: - colored = tintTexture(biome_grass_texture, (115, 175, 71)) - composite.alpha_over(img, colored, (0, 0), colored) + global biome_grass_texture + composite.alpha_over(img, biome_grass_texture, (0, 0), biome_grass_texture) return generate_texture_tuple(img, blockID) @@ -615,7 +615,7 @@ def generate_special_texture(blockID, data): if blockID == 18: # leaves - t = tintTexture(terrain_images[52], (37, 118, 25)) + t = terrain_images[52] img = _build_block(t, t, 18) return generate_texture_tuple(img, blockID) @@ -670,11 +670,9 @@ def generate_special_texture(blockID, data): if data == 0: # dead shrub texture = terrain_images[55] elif data == 1: # tall grass - texture = terrain_images[39].copy() - texture = tintTexture(texture, (115, 175, 71)) + texture = terrain_images[39] elif data == 2: # fern - texture = terrain_images[56].copy() - texture = tintTexture(texture, (115, 175, 71)) + texture = terrain_images[56] img = _build_block(texture, texture, blockID) return generate_texture_tuple(img,31) @@ -2182,15 +2180,22 @@ special_blocks = set([ 2, 6, 9, 17, 18, 20, 26, 23, 27, 28, 29, 31, 33, special_map = {} +# 0x10 means SNOW sides +special_map[2] = range(11) + [0x10,] # grass, grass has not ancildata but is + # used in the mod WildGrass, and this + # small fix shows the map as expected, + # and is harmless for normal maps special_map[6] = range(16) # saplings: usual, spruce, birch and future ones (rendered as usual saplings) special_map[9] = range(32) # water: spring,flowing, waterfall, and others (unknown) ancildata values, uses pseudo data special_map[17] = range(3) # wood: normal, birch and pine +special_map[18] = range(16) # leaves, birch, normal or pine leaves (not implemented) special_map[20] = range(32) # glass, used to only render the exterior surface, uses pseudo data special_map[26] = range(12) # bed, orientation special_map[23] = range(6) # dispensers, orientation special_map[27] = range(14) # powered rail, orientation/slope and powered/unpowered special_map[28] = range(6) # detector rail, orientation/slope special_map[29] = (0,1,2,3,4,5,8,9,10,11,12,13) # sticky piston body, orientation, pushed in/out +special_map[31] = range(3) # tall grass, dead shrub, fern and tall grass itself special_map[33] = (0,1,2,3,4,5,8,9,10,11,12,13) # normal piston body, orientation, pushed in/out special_map[34] = (0,1,2,3,4,5,8,9,10,11,12,13) # normal and sticky piston extension, orientation, sticky/normal special_map[35] = range(16) # wool, colored and white @@ -2232,26 +2237,11 @@ special_map[106] = (1,2,4,8) # vine, orientation special_map[108]= range(4) # red stairs, orientation special_map[109]= range(4) # stonebrick stairs, orientation -# grass and leaves are graysacle in terrain.png -# we treat them as special so we can manually tint them -# it is unknown how the specific tint (biomes) is calculated -# also, 0x10 means SNOW sides -special_map[2] = range(11) + [0x10,] # grass, grass has not ancildata but is - # used in the mod WildGrass, and this - # small fix shows the map as expected, - # and is harmless for normal maps -special_map[18] = range(16) # leaves, birch, normal or pine leaves (not implemented) -special_map[31] = range(3) # tall grass, dead shrub, fern and tall grass itself - # placeholders that are generated in generate() bgcolor = None terrain_images = None blockmap = None biome_grass_texture = None -biome_tall_grass_texture = None -biome_tall_fern_texture = None -biome_leaf_texture = None -biome_vine_texture = None specialblockmap = None def generate(path=None,texture_size=24,bgc = (26,26,26,0),north_direction='lower-left'): @@ -2273,13 +2263,9 @@ def generate(path=None,texture_size=24,bgc = (26,26,26,0),north_direction='lower blockmap = _build_blockimages() load_water() - # generate biome (still grayscale) leaf, grass textures - global biome_grass_texture, biome_leaf_texture, biome_tall_grass_texture, biome_tall_fern_texture, biome_vine_texture + # generate biome grass mask + global biome_grass_texture biome_grass_texture = _build_block(terrain_images[0], terrain_images[38], 2) - biome_leaf_texture = _build_block(terrain_images[52], terrain_images[52], 18) - biome_tall_grass_texture = _build_block(terrain_images[39], terrain_images[39], 31) - biome_tall_fern_texture = _build_block(terrain_images[56], terrain_images[56], 31) - biome_vine_texture = _build_block(terrain_images[143], terrain_images[143], 106) # generate the special blocks global specialblockmap, special_blocks @@ -2291,10 +2277,6 @@ def generate(path=None,texture_size=24,bgc = (26,26,26,0),north_direction='lower if texture_size != 24: # rescale biome textures. biome_grass_texture = biome_grass_texture.resize(texture_dimensions, Image.ANTIALIAS) - biome_leaf_texture = biome_leaf_texture.resize(texture_dimensions, Image.ANTIALIAS) - biome_tall_grass_texture = biome_tall_grass_texture.resize(texture_dimensions, Image.ANTIALIAS) - biome_tall_fern_texture = biome_tall_fern_texture.resize(texture_dimensions, Image.ANTIALIAS) - biome_vine_texture = biome_vine_texture.resize(texture_dimensions, Image.ANTIALIAS) # rescale the normal block images for i in range(len(blockmap)):