diff --git a/chunk.py b/chunk.py index 977fdfa..9db1194 100644 --- a/chunk.py +++ b/chunk.py @@ -284,7 +284,14 @@ class ChunkRenderer(object): self._load_up_right() return self._up_right_blocks up_right_blocks = property(_load_up_right_blocks) - + + def _load_up_right_skylight(self): + """Loads and returns lower-right skylight array""" + if not hasattr(self, "_up_right_skylight"): + self._load_up_right() + return self._up_right_skylight + up_right_skylight = property(_load_up_right_skylight) + def _load_up_left(self): """Loads and sets data from upper-left chunk""" chunk_path = self.world.get_region_path(self.chunkX, self.chunkY - 1) @@ -305,6 +312,13 @@ class ChunkRenderer(object): return self._up_left_blocks up_left_blocks = property(_load_up_left_blocks) + def _load_up_left_skylight(self): + """Loads and returns lower-right skylight array""" + if not hasattr(self, "_up_left_skylight"): + self._load_up_left() + return self._up_left_skylight + up_left_skylight = property(_load_up_left_skylight) + def generate_pseudo_ancildata(self,x,y,z,blockid, north_position = 0 ): """ Generates a pseudo ancillary data for blocks that depend of what are surrounded and don't have ancillary data diff --git a/setup.py b/setup.py index 0a36bcf..32360fb 100644 --- a/setup.py +++ b/setup.py @@ -55,7 +55,7 @@ except: pil_include = [] c_overviewer_files = ['src/main.c', 'src/composite.c', 'src/iterate.c', 'src/endian.c'] -c_overviewer_files += ['src/rendermodes.c', 'src/rendermode-normal.c', 'src/rendermode-lighting.c', 'src/rendermode-night.c', 'src/rendermode-spawn.c'] +c_overviewer_files += ['src/rendermodes.c', 'src/rendermode-normal.c', 'src/rendermode-lighting.c', 'src/rendermode-night.c', 'src/rendermode-spawn.c', 'src/rendermode-cave.c'] c_overviewer_files += ['src/Draw.c'] c_overviewer_includes = ['src/overviewer.h', 'src/rendermodes.h'] setup_kwargs['ext_modules'].append(Extension('c_overviewer', c_overviewer_files, include_dirs=['.', numpy_include] + pil_include, depends=c_overviewer_includes, extra_link_args=[])) diff --git a/src/rendermode-cave.c b/src/rendermode-cave.c new file mode 100644 index 0000000..85d7d93 --- /dev/null +++ b/src/rendermode-cave.c @@ -0,0 +1,190 @@ +/* + * This file is part of the Minecraft Overviewer. + * + * Minecraft Overviewer is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as published + * by the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Minecraft Overviewer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with the Overviewer. If not, see . + */ + +#include "overviewer.h" +#include +//~ +//~ /* figures out the black_coeff from a given skylight and blocklight, used in + //~ lighting calculations -- note this is *different* from the one in + //~ rendermode-lighting.c (the "skylight - 11" part) */ +//~ static float calculate_darkness(unsigned char skylight, unsigned char blocklight) { + //~ return 1.0f - powf(0.8f, 15.0 - MAX(blocklight, skylight - 11)); +//~ } + +static int +rendermode_cave_occluded(void *data, RenderState *state) { + int x = state->x, y = state->y, z = state->z; + RenderModeCave* self; + self = (RenderModeCave *)data; + + /* check if the block is touching skylight */ + if (z != 127) { + + if (getArrayByte3D(self->skylight, x, y, z+1) != 0) { + return 1; + } + + if ((x == 15)) { + if (self->up_right_skylight != Py_None) { + if (getArrayByte3D(self->up_right_skylight, 0, y, z) != 0) { + return 1; + } + } + } else { + if (getArrayByte3D(self->skylight, x+1, y, z) != 0) { + return 1; + } + } + + if (x == 0) { + if (self->left_skylight != Py_None) { + if (getArrayByte3D(self->left_skylight, 15, y, z) != 0) { + return 1; + } + } + } else { + if (getArrayByte3D(self->skylight, x-1, y, z) != 0) { + return 1; + } + } + + if (y == 15) { + if (self->right_skylight != Py_None) { + if (getArrayByte3D(self->right_skylight, 0, y, z) != 0) { + return 1; + } + } + } else { + if (getArrayByte3D(self->skylight, x, y+1, z) != 0) { + return 1; + } + } + + if (y == 0) { + if (self->up_left_skylight != Py_None) { + if (getArrayByte3D(self->up_left_skylight, 15, y, z) != 0) { + return 1; + } + } + } else { + if (getArrayByte3D(self->skylight, x, y-1, z) != 0) { + 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 don't skip */ + return 1; + } + + return 0; +} + +static int +rendermode_cave_start(void *data, RenderState *state) { + RenderModeCave* self; + self = (RenderModeCave *)data; + + /* first, chain up */ + int ret = rendermode_normal.start(data, state); + if (ret != 0) + return ret; + + /* 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"); + self->right_skylight = PyObject_GetAttrString(state->self, "right_skylight"); + self->up_left_skylight = PyObject_GetAttrString(state->self, "up_left_skylight"); + self->up_right_skylight = PyObject_GetAttrString(state->self, "up_right_skylight"); + + return 0; +} + +static void +rendermode_cave_finish(void *data, RenderState *state) { + RenderModeCave* self; + self = (RenderModeCave *)data; + + Py_DECREF(self->skylight); + Py_DECREF(self->left_skylight); + Py_DECREF(self->right_skylight); + Py_DECREF(self->up_left_skylight); + Py_DECREF(self->up_right_skylight); + + rendermode_normal.finish(data, state); +} + +static void +rendermode_cave_draw(void *data, RenderState *state, PyObject *src, PyObject *mask) { + /* nothing special to do */ + rendermode_normal.draw(data, state, src, mask); + +} + +RenderModeInterface rendermode_cave = { + "cave", "render only caves in normal mode", + sizeof(RenderModeCave), + rendermode_cave_start, + rendermode_cave_finish, + rendermode_cave_occluded, + rendermode_cave_draw, +}; diff --git a/src/rendermodes.c b/src/rendermodes.c index 0ef5550..08ac140 100644 --- a/src/rendermodes.c +++ b/src/rendermodes.c @@ -26,6 +26,7 @@ static RenderModeInterface *render_modes[] = { &rendermode_lighting, &rendermode_night, &rendermode_spawn, + &rendermode_cave, NULL }; diff --git a/src/rendermodes.h b/src/rendermodes.h index 3027a7f..babc551 100644 --- a/src/rendermodes.h +++ b/src/rendermodes.h @@ -119,4 +119,18 @@ typedef struct { } RenderModeSpawn; extern RenderModeInterface rendermode_spawn; +/* CAVE */ +typedef struct { + /* render blocks with lighting mode */ + RenderModeNormal parent; + /* data used to know where the surface is */ + PyObject *skylight; + PyObject *left_skylight; + PyObject *right_skylight; + PyObject *up_left_skylight; + PyObject *up_right_skylight; + +} RenderModeCave; +extern RenderModeInterface rendermode_cave; + #endif /* __RENDERMODES_H_INCLUDED__ */