From bc138ac859a558bc2e7af82232721884c04324b9 Mon Sep 17 00:00:00 2001 From: Aaron Griffith Date: Wed, 7 Sep 2011 17:16:43 -0400 Subject: [PATCH] created a distinct 'hidden' function --- overviewer_core/src/iterate.c | 2 +- overviewer_core/src/rendermode-cave.c | 121 ++++++++++++---------- overviewer_core/src/rendermode-lighting.c | 11 +- overviewer_core/src/rendermode-mineral.c | 7 ++ overviewer_core/src/rendermode-night.c | 7 ++ overviewer_core/src/rendermode-normal.c | 23 ++-- overviewer_core/src/rendermode-overlay.c | 10 ++ overviewer_core/src/rendermode-spawn.c | 7 ++ overviewer_core/src/rendermodes.c | 4 + overviewer_core/src/rendermodes.h | 21 +++- 10 files changed, 145 insertions(+), 68 deletions(-) diff --git a/overviewer_core/src/iterate.c b/overviewer_core/src/iterate.c index 8ad2691..6fd58bf 100644 --- a/overviewer_core/src/iterate.c +++ b/overviewer_core/src/iterate.c @@ -376,7 +376,7 @@ chunk_render(PyObject *self, PyObject *args) { /* get blockid */ state.block = getArrayByte3D(blocks_py, state.x, state.y, state.z); - if (state.block == 0) { + if (state.block == 0 || render_mode_hidden(rendermode, state.x, state.y, state.z)) { continue; } diff --git a/overviewer_core/src/rendermode-cave.c b/overviewer_core/src/rendermode-cave.c index e68578f..0b87377 100644 --- a/overviewer_core/src/rendermode-cave.c +++ b/overviewer_core/src/rendermode-cave.c @@ -80,13 +80,69 @@ touches_light(unsigned int x, unsigned int y, unsigned int z, } static int -rendermode_cave_occluded(void *data, RenderState *state, int x, int y, int z) { +rendermode_cave_occluded(void *data, RenderState *state, int x, int y, int z) { + /* first, check to see if it's "normally" occluded */ + if (rendermode_lighting.occluded(data, state, x, y, z)) + return 1; + + /* check for normal occlusion */ + /* use ajacent chunks, if not you get blocks spreaded in chunk edges */ + if ( (x == 0) && (y != 15) ) { + if (state->left_blocks != Py_None) { + if (!is_transparent(getArrayByte3D(state->left_blocks, 15, y, z)) && + !is_transparent(getArrayByte3D(state->blocks, x, y, z+1)) && + !is_transparent(getArrayByte3D(state->blocks, x, y+1, z))) { + return 1; + } + } else { + return 1; + } + } + + if ( (x != 0) && (y == 15) ) { + if (state->right_blocks != Py_None) { + if (!is_transparent(getArrayByte3D(state->blocks, x-1, y, z)) && + !is_transparent(getArrayByte3D(state->right_blocks, x, 0, z)) && + !is_transparent(getArrayByte3D(state->blocks, x, y, z+1))) { + return 1; + } + } else { + return 1; + } + } + + if ( (x == 0) && (y == 15) ) { + if ((state->left_blocks != Py_None) && + (state->right_blocks != Py_None)) { + if (!is_transparent(getArrayByte3D(state->left_blocks, 15, y, z)) && + !is_transparent(getArrayByte3D(state->right_blocks, x, 0, z)) && + !is_transparent(getArrayByte3D(state->blocks, x, y, z+1))) { + return 1; + } + } else { + return 1; + } + } + + if ( (x != 0) && (y != 15) && + !is_transparent(getArrayByte3D(state->blocks, x-1, y, z)) && + !is_transparent(getArrayByte3D(state->blocks, x, y, z+1)) && + !is_transparent(getArrayByte3D(state->blocks, x, y+1, z))) { + return 1; + } + + /* guess we're not occluded */ + return 0; +} + +static int +rendermode_cave_hidden(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_lighting.occluded(data, state, x, y, z)) + /* first, check to see if it's "normally" hidden */ + if (rendermode_lighting.hidden(data, state, x, y, z)) return 1; /* check if the block is touching skylight */ @@ -99,61 +155,14 @@ rendermode_cave_occluded(void *data, RenderState *state, int x, int y, int z) { if (self->only_lit && !touches_light(x, y, z, self->blocklight, self->left_blocklight, self->right_blocklight, self->up_left_blocklight, self->up_right_blocklight)) { return 1; } - - /* check for normal occlusion */ - /* use ajacent chunks, if not you get blocks spreaded in chunk edges */ - if ( (x == 0) && (y != 15) ) { - if (state->left_blocks != Py_None) { - if (!is_transparent(getArrayByte3D(state->left_blocks, 15, y, z)) && - !is_transparent(getArrayByte3D(state->blocks, x, y, z+1)) && - !is_transparent(getArrayByte3D(state->blocks, x, y+1, z))) { - return 1; - } - } else { - return 1; - } - } - - if ( (x != 0) && (y == 15) ) { - if (state->right_blocks != Py_None) { - if (!is_transparent(getArrayByte3D(state->blocks, x-1, y, z)) && - !is_transparent(getArrayByte3D(state->right_blocks, x, 0, z)) && - !is_transparent(getArrayByte3D(state->blocks, x, y, z+1))) { - return 1; - } - } else { - return 1; - } - } - - if ( (x == 0) && (y == 15) ) { - if ((state->left_blocks != Py_None) && - (state->right_blocks != Py_None)) { - if (!is_transparent(getArrayByte3D(state->left_blocks, 15, y, z)) && - !is_transparent(getArrayByte3D(state->right_blocks, x, 0, z)) && - !is_transparent(getArrayByte3D(state->blocks, x, y, z+1))) { - return 1; - } - } else { - return 1; - } - } - - if ( (x != 0) && (y != 15) && - !is_transparent(getArrayByte3D(state->blocks, x-1, y, z)) && - !is_transparent(getArrayByte3D(state->blocks, x, y, z+1)) && - !is_transparent(getArrayByte3D(state->blocks, x, y+1, z))) { - return 1; - } - } else { /* if z == 127 skip */ return 1; } - /* check for lakes and seas and don't render them */ - /* at this point of the code the block has no skylight - * and is not occluded, but a deep sea can fool these - * 2 tests */ + /* check for lakes and seas and don't render them + * at this point of the code the block has no skylight + * but a deep sea can be completely dark + */ if ((getArrayByte3D(state->blocks, x, y, z) == 9) || (getArrayByte3D(state->blocks, x, y, z+1) == 9)) { @@ -169,8 +178,7 @@ rendermode_cave_occluded(void *data, RenderState *state, int x, int y, int z) { } } } - - + return 0; } @@ -284,5 +292,6 @@ RenderModeInterface rendermode_cave = { rendermode_cave_start, rendermode_cave_finish, rendermode_cave_occluded, + rendermode_cave_hidden, rendermode_cave_draw, }; diff --git a/overviewer_core/src/rendermode-lighting.c b/overviewer_core/src/rendermode-lighting.c index 20ef874..9897d6e 100644 --- a/overviewer_core/src/rendermode-lighting.c +++ b/overviewer_core/src/rendermode-lighting.c @@ -212,14 +212,12 @@ 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); - int occluded = render_mode_occluded(state->rendermode, x, y, z); - if (!occluded && !is_transparent(block)) { + if (!is_transparent(block) && !render_mode_hidden(state->rendermode, x, y, z)) { /* this face isn't visible, so don't draw anything */ return; } @@ -306,6 +304,12 @@ rendermode_lighting_occluded(void *data, RenderState *state, int x, int y, int z return rendermode_normal.occluded(data, state, x, y, z); } +static int +rendermode_lighting_hidden(void *data, RenderState *state, int x, int y, int z) { + /* no special hiding here */ + return rendermode_normal.hidden(data, state, x, y, z); +} + static void rendermode_lighting_draw(void *data, RenderState *state, PyObject *src, PyObject *mask, PyObject *mask_light) { RenderModeLighting* self; @@ -356,5 +360,6 @@ RenderModeInterface rendermode_lighting = { rendermode_lighting_start, rendermode_lighting_finish, rendermode_lighting_occluded, + rendermode_lighting_hidden, rendermode_lighting_draw, }; diff --git a/overviewer_core/src/rendermode-mineral.c b/overviewer_core/src/rendermode-mineral.c index 3a74d5a..e3887b9 100644 --- a/overviewer_core/src/rendermode-mineral.c +++ b/overviewer_core/src/rendermode-mineral.c @@ -136,6 +136,12 @@ rendermode_mineral_occluded(void *data, RenderState *state, int x, int y, int z) return rendermode_overlay.occluded(data, state, x, y, z); } +static int +rendermode_mineral_hidden(void *data, RenderState *state, int x, int y, int z) { + /* no special hiding here */ + return rendermode_overlay.hidden(data, state, x, y, z); +} + static void rendermode_mineral_draw(void *data, RenderState *state, PyObject *src, PyObject *mask, PyObject *mask_light) { /* draw normally */ @@ -155,5 +161,6 @@ RenderModeInterface rendermode_mineral = { rendermode_mineral_start, rendermode_mineral_finish, rendermode_mineral_occluded, + rendermode_mineral_hidden, rendermode_mineral_draw, }; diff --git a/overviewer_core/src/rendermode-night.c b/overviewer_core/src/rendermode-night.c index f1d38bd..32281a6 100644 --- a/overviewer_core/src/rendermode-night.c +++ b/overviewer_core/src/rendermode-night.c @@ -53,6 +53,12 @@ rendermode_night_occluded(void *data, RenderState *state, int x, int y, int z) { return rendermode_lighting.occluded(data, state, x, y, z); } +static int +rendermode_night_hidden(void *data, RenderState *state, int x, int y, int z) { + /* no special hiding here */ + return rendermode_lighting.hidden(data, state, x, y, z); +} + static void rendermode_night_draw(void *data, RenderState *state, PyObject *src, PyObject *mask, PyObject *mask_light) { /* nothing special to do */ @@ -67,5 +73,6 @@ RenderModeInterface rendermode_night = { rendermode_night_start, rendermode_night_finish, rendermode_night_occluded, + rendermode_night_hidden, rendermode_night_draw, }; diff --git a/overviewer_core/src/rendermode-normal.c b/overviewer_core/src/rendermode-normal.c index 547fb8c..5c0ac4f 100644 --- a/overviewer_core/src/rendermode-normal.c +++ b/overviewer_core/src/rendermode-normal.c @@ -135,13 +135,10 @@ rendermode_normal_finish(void *data, RenderState *state) { static int rendermode_normal_occluded(void *data, RenderState *state, int x, int y, int z) { - RenderModeNormal *self = (RenderModeNormal *)data; - - if (z > self->max_depth || z < self->min_depth) { - return 1; - } - - if ( (x != 0) && (y != 15) && (z != self->max_depth) && + if ( (x != 0) && (y != 15) && (z != 127) && + !render_mode_hidden(state->rendermode, x-1, y, z) && + !render_mode_hidden(state->rendermode, x, y, z+1) && + !render_mode_hidden(state->rendermode, x, y+1, z) && !is_transparent(getArrayByte3D(state->blocks, x-1, y, z)) && !is_transparent(getArrayByte3D(state->blocks, x, y, z+1)) && !is_transparent(getArrayByte3D(state->blocks, x, y+1, z))) { @@ -151,6 +148,17 @@ rendermode_normal_occluded(void *data, RenderState *state, int x, int y, int z) return 0; } +static int +rendermode_normal_hidden(void *data, RenderState *state, int x, int y, int z) { + RenderModeNormal *self = (RenderModeNormal *)data; + + if (z > self->max_depth || z < self->min_depth) { + return 1; + } + + return 0; +} + static void rendermode_normal_draw(void *data, RenderState *state, PyObject *src, PyObject *mask, PyObject *mask_light) { RenderModeNormal *self = (RenderModeNormal *)data; @@ -298,5 +306,6 @@ RenderModeInterface rendermode_normal = { rendermode_normal_start, rendermode_normal_finish, rendermode_normal_occluded, + rendermode_normal_hidden, rendermode_normal_draw, }; diff --git a/overviewer_core/src/rendermode-overlay.c b/overviewer_core/src/rendermode-overlay.c index 769c445..b909e33 100644 --- a/overviewer_core/src/rendermode-overlay.c +++ b/overviewer_core/src/rendermode-overlay.c @@ -59,6 +59,9 @@ rendermode_overlay_finish(void *data, RenderState *state) { static int rendermode_overlay_occluded(void *data, RenderState *state, int x, int y, int z) { if ( (x != 0) && (y != 15) && (z != 127) && + !render_mode_hidden(state->rendermode, x-1, y, z) && + !render_mode_hidden(state->rendermode, x, y, z+1) && + !render_mode_hidden(state->rendermode, x, y+1, z) && !is_transparent(getArrayByte3D(state->blocks, x-1, y, z)) && !is_transparent(getArrayByte3D(state->blocks, x, y, z+1)) && !is_transparent(getArrayByte3D(state->blocks, x, y+1, z))) { @@ -68,6 +71,12 @@ rendermode_overlay_occluded(void *data, RenderState *state, int x, int y, int z) return 0; } +static int +rendermode_overlay_hidden(void *data, RenderState *state, int x, int y, int z) { + /* overlays hide nothing by default */ + return 0; +} + static void rendermode_overlay_draw(void *data, RenderState *state, PyObject *src, PyObject *mask, PyObject *mask_light) { RenderModeOverlay *self = (RenderModeOverlay *)data; @@ -132,5 +141,6 @@ RenderModeInterface rendermode_overlay = { rendermode_overlay_start, rendermode_overlay_finish, rendermode_overlay_occluded, + rendermode_overlay_hidden, rendermode_overlay_draw, }; diff --git a/overviewer_core/src/rendermode-spawn.c b/overviewer_core/src/rendermode-spawn.c index b812444..ffd478e 100644 --- a/overviewer_core/src/rendermode-spawn.c +++ b/overviewer_core/src/rendermode-spawn.c @@ -101,6 +101,12 @@ rendermode_spawn_occluded(void *data, RenderState *state, int x, int y, int z) { return rendermode_overlay.occluded(data, state, x, y, z); } +static int +rendermode_spawn_hidden(void *data, RenderState *state, int x, int y, int z) { + /* no special hiding here */ + return rendermode_overlay.hidden(data, state, x, y, z); +} + static void rendermode_spawn_draw(void *data, RenderState *state, PyObject *src, PyObject *mask, PyObject *mask_light) { /* draw normally */ @@ -115,5 +121,6 @@ RenderModeInterface rendermode_spawn = { rendermode_spawn_start, rendermode_spawn_finish, rendermode_spawn_occluded, + rendermode_spawn_hidden, rendermode_spawn_draw, }; diff --git a/overviewer_core/src/rendermodes.c b/overviewer_core/src/rendermodes.c index 98c0df3..45ff887 100644 --- a/overviewer_core/src/rendermodes.c +++ b/overviewer_core/src/rendermodes.c @@ -167,6 +167,10 @@ int render_mode_occluded(RenderMode *self, int x, int y, int z) { return self->iface->occluded(self->mode, self->state, x, y, z); } +int render_mode_hidden(RenderMode *self, int x, int y, int z) { + return self->iface->hidden(self->mode, self->state, x, y, z); +} + void render_mode_draw(RenderMode *self, PyObject *img, PyObject *mask, PyObject *mask_light) { self->iface->draw(self->mode, self->state, img, mask, mask_light); } diff --git a/overviewer_core/src/rendermodes.h b/overviewer_core/src/rendermodes.h index 52473f3..ab257e2 100644 --- a/overviewer_core/src/rendermodes.h +++ b/overviewer_core/src/rendermodes.h @@ -62,12 +62,30 @@ struct _RenderModeInterface { /* may return non-zero on error, last arg is options */ int (*start)(void *, RenderState *, PyObject *); void (*finish)(void *, RenderState *); - /* returns non-zero to skip rendering this block */ + /* returns non-zero to skip rendering this block because it's not visible */ int (*occluded)(void *, RenderState *, int, int, int); + /* returns non-zero to skip rendering this block because the user doesn't + * want it visible */ + int (*hidden)(void *, RenderState *, int, int, int); /* last two arguments are img and mask, from texture lookup */ void (*draw)(void *, RenderState *, PyObject *, PyObject *, PyObject *); }; +/* A quick note about the difference between occluded and hidden: + * + * Occluded should be used to tell the renderer that a block will not be + * visible in the final image because other blocks will be drawn on top of + * it. This is a potentially *expensive* check that should be used rarely, + * usually only once per block. The idea is this check is expensive, but not + * as expensive as drawing the block itself. + * + * Hidden is used to tell the renderer not to draw the block, usually because + * the current rendermode depends on those blocks being hidden to do its + * job. For example, cave mode uses this to hide non-cave blocks. This check + * should be *cheap*, as it's potentially called many times per block. For + * example, in lighting mode it is called at most 4 times per block. + */ + /* wrapper for passing around rendermodes */ struct _RenderMode { void *mode; @@ -79,6 +97,7 @@ struct _RenderMode { RenderMode *render_mode_create(const char *mode, RenderState *state); void render_mode_destroy(RenderMode *self); int render_mode_occluded(RenderMode *self, int x, int y, int z); +int render_mode_hidden(RenderMode *self, int x, int y, int z); void render_mode_draw(RenderMode *self, PyObject *img, PyObject *mask, PyObject *mask_light); /* helper function for reading in rendermode options