From f23d3ddac9b5d59da1ad649b3787c816edcef38d Mon Sep 17 00:00:00 2001 From: Aaron Griffith Date: Mon, 28 Mar 2011 03:40:02 -0400 Subject: [PATCH] converted spawn into a overlay-based rendermode --- chunk.py | 1 - googlemap.py | 2 +- overviewer.py | 2 +- src/rendermode-spawn.c | 117 ++++++++++++++++++----------------------- src/rendermodes.c | 4 -- src/rendermodes.h | 9 ++-- 6 files changed, 58 insertions(+), 77 deletions(-) diff --git a/chunk.py b/chunk.py index 56e58ef..bfe7e24 100644 --- a/chunk.py +++ b/chunk.py @@ -502,7 +502,6 @@ def generate_facemasks(): return (top, left, right) facemasks = generate_facemasks() black_color = Image.new("RGB", (24,24), (0,0,0)) -red_color = Image.new("RGB", (24,24), (229,36,38)) white_color = Image.new("RGB", (24,24), (255,255,255)) # Render 128 different color images for color coded depth blending in cave mode diff --git a/googlemap.py b/googlemap.py index 9ae846a..29e197f 100644 --- a/googlemap.py +++ b/googlemap.py @@ -96,7 +96,7 @@ class MapGen(object): # create generated map type data, from given quadtrees # FIXME hook this into render_modes in setup.py, somehow - overlay_types = ['overlay'] + overlay_types = ['spawn'] maptypedata = map(lambda q: {'label' : q.rendermode.capitalize(), 'path' : q.tiledir, 'overlay' : q.rendermode in overlay_types}, diff --git a/overviewer.py b/overviewer.py index 7082d0c..4ac0e8d 100755 --- a/overviewer.py +++ b/overviewer.py @@ -65,7 +65,7 @@ def main(): parser.add_option("-d", "--delete", dest="delete", help="Clear all caches. Next time you render your world, it will have to start completely over again. This is probably not a good idea for large worlds. Use this if you change texture packs and want to re-render everything.", action="store_true", commandLineOnly=True) parser.add_option("--chunklist", dest="chunklist", help="A file containing, on each line, a path to a chunkfile to update. Instead of scanning the world directory for chunks, it will just use this list. Normal caching rules still apply.") # TODO hook this up to render_modes in setup.py - parser.add_option("--rendermodes", dest="rendermode", help="Specifies the render type: normal (default), lighting, night, or spawn.", type="choice", choices=["normal", "lighting", "night", "spawn", "overlay"], required=True, default="normal", listify=True) + parser.add_option("--rendermodes", dest="rendermode", help="Specifies the render type: normal (default), lighting, night, or spawn.", type="choice", choices=["normal", "lighting", "night", "spawn"], required=True, default="normal", listify=True) parser.add_option("--imgformat", dest="imgformat", help="The image output format to use. Currently supported: png(default), jpg. NOTE: png will always be used as the intermediate image format.", configFileOnly=True ) parser.add_option("--optimize-img", dest="optimizeimg", help="If using png, perform image file size optimizations on the output. Specify 1 for pngcrush, 2 for pngcrush+optipng+advdef. This may double (or more) render times, but will produce up to 30% smaller images. NOTE: requires corresponding programs in $PATH or %PATH%", configFileOnly=True) parser.add_option("--web-assets-hook", dest="web_assets_hook", help="If provided, run this function after the web assets have been copied, but before actual tile rendering begins. It should accept a QuadtreeGen object as its only argument.", action="store", metavar="SCRIPT", type="function", configFileOnly=True) diff --git a/src/rendermode-spawn.c b/src/rendermode-spawn.c index 1a7c96a..b0b78a4 100644 --- a/src/rendermode-spawn.c +++ b/src/rendermode-spawn.c @@ -18,21 +18,63 @@ #include "overviewer.h" #include +static void get_color(void *data, RenderState *state, + unsigned char *r, unsigned char *g, unsigned char *b, unsigned char *a) { + + RenderModeSpawn* self = (RenderModeSpawn *)data; + int x = state->x, y = state->y, z = state->z; + unsigned char blocklight, skylight; + PyObject *block_py; + + /* set a nice, pretty red color */ + *r = 229; + *g = 36; + *b = 38; + + /* default to no overlay, until told otherwise */ + *a = 0; + + /* if we're at the top, skip */ + if (z == 127) + return; + + block_py = PyInt_FromLong(state->block); + if (PySequence_Contains(self->nospawn_blocks, block_py)) { + /* nothing can spawn on this */ + Py_DECREF(block_py); + return; + } + Py_DECREF(block_py); + + blocklight = getArrayByte3D(self->blocklight, x, y, z+1); + skylight = getArrayByte3D(self->skylight, x, y, z+1); + + if (MAX(blocklight, skylight) <= 7) { + /* hostile mobs spawn in daylight */ + *a = 240; + } else if (MAX(blocklight, skylight - 11) <= 7) { + /* hostile mobs spawn at night */ + *a = 150; + } +} + static int rendermode_spawn_start(void *data, RenderState *state) { RenderModeSpawn* self; /* first, chain up */ - int ret = rendermode_night.start(data, state); + int ret = rendermode_overlay.start(data, state); if (ret != 0) return ret; /* now do custom initializations */ self = (RenderModeSpawn *)data; - self->solid_blocks = PyObject_GetAttrString(state->chunk, "solid_blocks"); self->nospawn_blocks = PyObject_GetAttrString(state->chunk, "nospawn_blocks"); - self->fluid_blocks = PyObject_GetAttrString(state->chunk, "fluid_blocks"); - self->red_color = PyObject_GetAttrString(state->chunk, "red_color"); + self->blocklight = PyObject_GetAttrString(state->self, "blocklight"); + self->skylight = PyObject_GetAttrString(state->self, "skylight"); + + /* setup custom color */ + self->parent.get_color = get_color; return 0; } @@ -40,81 +82,26 @@ rendermode_spawn_start(void *data, RenderState *state) { static void rendermode_spawn_finish(void *data, RenderState *state) { /* first free all *our* stuff */ - RenderModeSpawn* self = (RenderModeSpawn *)data; + RenderModeSpawn* self = (RenderModeSpawn *)data; - Py_DECREF(self->solid_blocks); Py_DECREF(self->nospawn_blocks); - Py_DECREF(self->fluid_blocks); + Py_DECREF(self->blocklight); + Py_DECREF(self->skylight); /* now, chain up */ - rendermode_night.finish(data, state); + rendermode_overlay.finish(data, state); } static int rendermode_spawn_occluded(void *data, RenderState *state) { /* no special occlusion here */ - return rendermode_night.occluded(data, state); + return rendermode_overlay.occluded(data, state); } static void rendermode_spawn_draw(void *data, RenderState *state, PyObject *src, PyObject *mask) { - /* different versions of self (spawn, lighting) */ - RenderModeSpawn* self = (RenderModeSpawn *)data; - RenderModeLighting *lighting = (RenderModeLighting *)self; - - int x = state->x, y = state->y, z = state->z; - PyObject *old_black_color = NULL; - - /* figure out the appropriate darkness: - this block for transparents, the block above for non-transparent */ - float darkness = 0.0; - if (is_transparent(state->block)) { - darkness = get_lighting_coefficient((RenderModeLighting *)self, state, x, y, z, NULL); - } else { - darkness = get_lighting_coefficient((RenderModeLighting *)self, state, x, y, z+1, NULL); - } - - /* if it's dark enough... */ - if (darkness > 0.8) { - PyObject *block_py = PyInt_FromLong(state->block); - - /* make sure it's solid */ - if (PySequence_Contains(self->solid_blocks, block_py)) { - int spawnable = 1; - - /* not spawnable if its in the nospawn list */ - if (PySequence_Contains(self->nospawn_blocks, block_py)) - spawnable = 0; - - /* check the block above for solid or fluid */ - if (spawnable && z != 127) { - PyObject *top_block_py = PyInt_FromLong(getArrayByte3D(state->blocks, x, y, z+1)); - if (PySequence_Contains(self->solid_blocks, top_block_py) || - PySequence_Contains(self->fluid_blocks, top_block_py)) { - - spawnable = 0; - } - - Py_DECREF(top_block_py); - } - - /* if we passed all the checks, replace black_color with red_color */ - if (spawnable) { - old_black_color = lighting->black_color; - lighting->black_color = self->red_color; - } - } - - Py_DECREF(block_py); - } - /* draw normally */ - rendermode_night.draw(data, state, src, mask); - - /* reset black_color, if needed */ - if (old_black_color != NULL) { - lighting->black_color = old_black_color; - } + rendermode_overlay.draw(data, state, src, mask); } RenderModeInterface rendermode_spawn = { diff --git a/src/rendermodes.c b/src/rendermodes.c index 46cc432..f4fbe89 100644 --- a/src/rendermodes.c +++ b/src/rendermodes.c @@ -31,10 +31,6 @@ RenderModeInterface *get_render_mode(RenderState *state) { iface = &rendermode_night; } else if (strcmp(rendermode, "spawn") == 0) { iface = &rendermode_spawn; - } else if (strcmp(rendermode, "overlay") == 0) { - /* TODO temporarily use overlay directly, but later on - you want to use overlay-derived modes */ - iface = &rendermode_overlay; } Py_DECREF(rendermode_py); diff --git a/src/rendermodes.h b/src/rendermodes.h index 6129980..a0d18a4 100644 --- a/src/rendermodes.h +++ b/src/rendermodes.h @@ -115,13 +115,12 @@ extern RenderModeInterface rendermode_night; /* SPAWN */ typedef struct { - /* inherits from night */ - RenderModeNight parent; + /* inherits from overlay */ + RenderModeOverlay parent; /* used to figure out which blocks are spawnable */ - PyObject *solid_blocks, *nospawn_blocks, *fluid_blocks; - /* replacement for black_color */ - PyObject *red_color; + PyObject *nospawn_blocks; + PyObject *skylight, *blocklight; } RenderModeSpawn; extern RenderModeInterface rendermode_spawn;