diff --git a/chunk.py b/chunk.py index a4b8bf6..1a1ad14 100644 --- a/chunk.py +++ b/chunk.py @@ -476,6 +476,10 @@ def generate_facemasks(): for x,y in [(3,4), (7,2), (11,0)]: top.putpixel((x,y), 255) + # special fix for chunk boundary stipple + for x,y in [(13,11), (17,9), (21,7)]: + right.putpixel((x,y), 0) + return (top, left, right) facemasks = generate_facemasks() black_color = Image.new("RGB", (24,24), (0,0,0)) diff --git a/src/iterate.c b/src/iterate.c index 5d82aaa..ca56f9b 100644 --- a/src/iterate.c +++ b/src/iterate.c @@ -317,7 +317,7 @@ chunk_render(PyObject *self, PyObject *args) { /* set up the render mode */ rendermode_py = PyObject_GetAttrString(state.self, "rendermode"); - rendermode = render_mode_create(PyString_AsString(rendermode_py), &state); + state.rendermode = rendermode = render_mode_create(PyString_AsString(rendermode_py), &state); Py_DECREF(rendermode_py); if (rendermode == NULL) { return Py_BuildValue("i", "-1"); @@ -386,7 +386,7 @@ chunk_render(PyObject *self, PyObject *args) { blockid = PyInt_FromLong(state.block); // check for occlusion - if (render_mode_occluded(rendermode)) { + if (render_mode_occluded(rendermode, state.x, state.y, state.z)) { continue; } diff --git a/src/overviewer.h b/src/overviewer.h index a0c5316..9befb18 100644 --- a/src/overviewer.h +++ b/src/overviewer.h @@ -52,6 +52,9 @@ PyObject *tint_with_mask(PyObject *dest, unsigned char sr, unsigned char sg, unsigned char sb, unsigned char sa, PyObject *mask, int dx, int dy, int xsize, int ysize); +/* forward declaration of RenderMode object */ +typedef struct _RenderMode RenderMode; + /* in iterate.c */ typedef struct { /* the ChunkRenderer object */ @@ -61,6 +64,9 @@ typedef struct { PyObject *textures; PyObject *chunk; + /* the current render mode in use */ + RenderMode *rendermode; + /* the rest only make sense for occluded() and draw() !! */ /* the tile image and destination */ diff --git a/src/rendermode-cave.c b/src/rendermode-cave.c index 012a305..6d8a7cb 100644 --- a/src/rendermode-cave.c +++ b/src/rendermode-cave.c @@ -80,13 +80,13 @@ touches_light(unsigned int x, unsigned int y, unsigned int z, } static int -rendermode_cave_occluded(void *data, RenderState *state) { - int x = state->x, y = state->y, z = state->z, dz = 0; +rendermode_cave_occluded(void *data, RenderState *state, int x, int y, int z) { RenderModeCave* self; + int dz = 0; self = (RenderModeCave *)data; /* first, check to see if it's "normally" occluded */ - if (rendermode_normal.occluded(data, state)) + if (rendermode_lighting.occluded(data, state, x, y, z)) return 1; /* check if the block is touching skylight */ @@ -182,7 +182,7 @@ rendermode_cave_start(void *data, RenderState *state, PyObject *options) { self = (RenderModeCave *)data; /* first, chain up */ - ret = rendermode_normal.start(data, state, options); + ret = rendermode_lighting.start(data, state, options); if (ret != 0) return ret; @@ -200,6 +200,13 @@ rendermode_cave_start(void *data, RenderState *state, PyObject *options) { self->only_lit = 0; } + opt = PyDict_GetItemString(options, "lighting"); + if (opt) { + self->lighting = PyObject_IsTrue(opt); + } else { + self->lighting = 0; + } + /* if there's skylight we are in the surface! */ self->skylight = PyObject_GetAttrString(state->self, "skylight"); self->left_skylight = PyObject_GetAttrString(state->self, "left_skylight"); @@ -242,7 +249,7 @@ rendermode_cave_finish(void *data, RenderState *state) { Py_DECREF(self->depth_colors); - rendermode_normal.finish(data, state); + rendermode_lighting.finish(data, state); } static void @@ -255,7 +262,11 @@ rendermode_cave_draw(void *data, RenderState *state, PyObject *src, PyObject *ma r = 0, g = 0, b = 0; /* draw the normal block */ - rendermode_normal.draw(data, state, src, mask, mask_light); + if (self->lighting) { + rendermode_lighting.draw(data, state, src, mask, mask_light); + } else { + rendermode_normal.draw(data, state, src, mask, mask_light); + } if (self->depth_tinting) { /* get the colors and tint and tint */ @@ -271,13 +282,14 @@ rendermode_cave_draw(void *data, RenderState *state, PyObject *src, PyObject *ma static RenderModeOption rendermode_cave_options[] = { {"depth_tinting", "tint caves based on how deep they are (default: True)"}, {"only_lit", "only render lit caves (default: False)"}, + {"lighting", "render caves with lighting enabled (default: False)"}, {NULL, NULL} }; RenderModeInterface rendermode_cave = { - "cave", "render only caves in normal mode", + "cave", "render only caves", rendermode_cave_options, - &rendermode_normal, + &rendermode_lighting, sizeof(RenderModeCave), rendermode_cave_start, rendermode_cave_finish, diff --git a/src/rendermode-lighting.c b/src/rendermode-lighting.c index 8f27084..f4c8bc6 100644 --- a/src/rendermode-lighting.c +++ b/src/rendermode-lighting.c @@ -83,12 +83,6 @@ get_lighting_coefficient(RenderModeLighting *self, RenderState *state, block = getArrayByte3D(blocks, local_x, local_y, local_z); - /* if this block is opaque, use a fully-lit coeff instead - to prevent stippled lines along chunk boundaries! */ - if (!is_transparent(block)) { - return self->calculate_darkness(15, 0); - } - /* only do special half-step handling if no authoratative pointer was passed in, which is a sign that we're recursing */ if ((block == 44 || block == 53 || block == 67) && authoratative == NULL) { @@ -154,11 +148,14 @@ static inline void do_shading_with_mask(RenderModeLighting *self, RenderState *state, int x, int y, int z, PyObject *mask) { float black_coeff; - + PyObject *blocks; + /* first, check for occlusion if the block is in the local chunk */ if (x >= 0 && x < 16 && y >= 0 && y < 16 && z >= 0 && z < 128) { unsigned char block = getArrayByte3D(state->blocks, x, y, z); - if (!is_transparent(block)) { + int occluded = render_mode_occluded(state->rendermode, x, y, z); + + if (!occluded && !is_transparent(block)) { /* this face isn't visible, so don't draw anything */ return; } @@ -230,9 +227,9 @@ rendermode_lighting_finish(void *data, RenderState *state) { } static int -rendermode_lighting_occluded(void *data, RenderState *state) { +rendermode_lighting_occluded(void *data, RenderState *state, int x, int y, int z) { /* no special occlusion here */ - return rendermode_normal.occluded(data, state); + return rendermode_normal.occluded(data, state, x, y, z); } static void diff --git a/src/rendermode-night.c b/src/rendermode-night.c index f3edc68..f1d38bd 100644 --- a/src/rendermode-night.c +++ b/src/rendermode-night.c @@ -48,9 +48,9 @@ rendermode_night_finish(void *data, RenderState *state) { } static int -rendermode_night_occluded(void *data, RenderState *state) { +rendermode_night_occluded(void *data, RenderState *state, int x, int y, int z) { /* no special occlusion here */ - return rendermode_lighting.occluded(data, state); + return rendermode_lighting.occluded(data, state, x, y, z); } static void diff --git a/src/rendermode-normal.c b/src/rendermode-normal.c index c9ac6a8..85c01ac 100644 --- a/src/rendermode-normal.c +++ b/src/rendermode-normal.c @@ -144,9 +144,8 @@ rendermode_normal_finish(void *data, RenderState *state) { } static int -rendermode_normal_occluded(void *data, RenderState *state) { +rendermode_normal_occluded(void *data, RenderState *state, int x, int y, int z) { RenderModeNormal *self = (RenderModeNormal *)data; - int x = state->x, y = state->y, z = state->z; if (z > self->max_depth || z < self->min_depth) { return 1; diff --git a/src/rendermode-overlay.c b/src/rendermode-overlay.c index 342a6f9..769c445 100644 --- a/src/rendermode-overlay.c +++ b/src/rendermode-overlay.c @@ -57,9 +57,7 @@ rendermode_overlay_finish(void *data, RenderState *state) { } static int -rendermode_overlay_occluded(void *data, RenderState *state) { - int x = state->x, y = state->y, z = state->z; - +rendermode_overlay_occluded(void *data, RenderState *state, int x, int y, int z) { if ( (x != 0) && (y != 15) && (z != 127) && !is_transparent(getArrayByte3D(state->blocks, x-1, y, z)) && !is_transparent(getArrayByte3D(state->blocks, x, y, z+1)) && diff --git a/src/rendermode-spawn.c b/src/rendermode-spawn.c index 4fff748..b812444 100644 --- a/src/rendermode-spawn.c +++ b/src/rendermode-spawn.c @@ -96,9 +96,9 @@ rendermode_spawn_finish(void *data, RenderState *state) { } static int -rendermode_spawn_occluded(void *data, RenderState *state) { +rendermode_spawn_occluded(void *data, RenderState *state, int x, int y, int z) { /* no special occlusion here */ - return rendermode_overlay.occluded(data, state); + return rendermode_overlay.occluded(data, state, x, y, z); } static void diff --git a/src/rendermodes.c b/src/rendermodes.c index eb88517..e03921c 100644 --- a/src/rendermodes.c +++ b/src/rendermodes.c @@ -164,8 +164,8 @@ void render_mode_destroy(RenderMode *self) { free(self); } -int render_mode_occluded(RenderMode *self) { - return self->iface->occluded(self->mode, self->state); +int render_mode_occluded(RenderMode *self, int x, int y, int z) { + return self->iface->occluded(self->mode, self->state, x, y, z); } void render_mode_draw(RenderMode *self, PyObject *img, PyObject *mask, PyObject *mask_light) { diff --git a/src/rendermodes.h b/src/rendermodes.h index 928c0ac..120726c 100644 --- a/src/rendermodes.h +++ b/src/rendermodes.h @@ -36,6 +36,7 @@ #define __RENDERMODES_H_INCLUDED__ #include +#include "overviewer.h" typedef struct { const char *name; @@ -62,22 +63,22 @@ struct _RenderModeInterface { int (*start)(void *, RenderState *, PyObject *); void (*finish)(void *, RenderState *); /* returns non-zero to skip rendering this block */ - int (*occluded)(void *, RenderState *); + int (*occluded)(void *, RenderState *, int, int, int); /* last two arguments are img and mask, from texture lookup */ void (*draw)(void *, RenderState *, PyObject *, PyObject *, PyObject *); }; /* wrapper for passing around rendermodes */ -typedef struct { +struct _RenderMode { void *mode; RenderModeInterface *iface; RenderState *state; -} RenderMode; +}; /* functions for creating / using rendermodes */ RenderMode *render_mode_create(const char *mode, RenderState *state); void render_mode_destroy(RenderMode *self); -int render_mode_occluded(RenderMode *self); +int render_mode_occluded(RenderMode *self, int x, int y, int z); void render_mode_draw(RenderMode *self, PyObject *img, PyObject *mask, PyObject *mask_light); /* python metadata bindings */ @@ -167,7 +168,7 @@ extern RenderModeInterface rendermode_spawn; /* CAVE */ typedef struct { /* render blocks with lighting mode */ - RenderModeNormal parent; + RenderModeLighting parent; /* data used to know where the surface is */ PyObject *skylight; @@ -188,6 +189,7 @@ typedef struct { int depth_tinting; int only_lit; + int lighting; } RenderModeCave; extern RenderModeInterface rendermode_cave;