0

converted spawn into a overlay-based rendermode

This commit is contained in:
Aaron Griffith
2011-03-28 03:40:02 -04:00
parent 83db528d81
commit f23d3ddac9
6 changed files with 58 additions and 77 deletions

View File

@@ -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

View File

@@ -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},

View File

@@ -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)

View File

@@ -18,21 +18,63 @@
#include "overviewer.h"
#include <math.h>
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 = {

View File

@@ -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);

View File

@@ -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;