0

created a distinct 'hidden' function

This commit is contained in:
Aaron Griffith
2011-09-07 17:16:43 -04:00
parent 43629e928b
commit bc138ac859
10 changed files with 145 additions and 68 deletions

View File

@@ -376,7 +376,7 @@ chunk_render(PyObject *self, PyObject *args) {
/* get blockid */ /* get blockid */
state.block = getArrayByte3D(blocks_py, state.x, state.y, state.z); 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; continue;
} }

View File

@@ -80,13 +80,69 @@ touches_light(unsigned int x, unsigned int y, unsigned int z,
} }
static int 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; RenderModeCave* self;
int dz = 0; int dz = 0;
self = (RenderModeCave *)data; self = (RenderModeCave *)data;
/* first, check to see if it's "normally" occluded */ /* first, check to see if it's "normally" hidden */
if (rendermode_lighting.occluded(data, state, x, y, z)) if (rendermode_lighting.hidden(data, state, x, y, z))
return 1; return 1;
/* check if the block is touching skylight */ /* 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)) { 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; 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 */ } else { /* if z == 127 skip */
return 1; return 1;
} }
/* check for lakes and seas and don't render them */ /* check for lakes and seas and don't render them
/* at this point of the code the block has no skylight * at this point of the code the block has no skylight
* and is not occluded, but a deep sea can fool these * but a deep sea can be completely dark
* 2 tests */ */
if ((getArrayByte3D(state->blocks, x, y, z) == 9) || if ((getArrayByte3D(state->blocks, x, y, z) == 9) ||
(getArrayByte3D(state->blocks, x, y, z+1) == 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; return 0;
} }
@@ -284,5 +292,6 @@ RenderModeInterface rendermode_cave = {
rendermode_cave_start, rendermode_cave_start,
rendermode_cave_finish, rendermode_cave_finish,
rendermode_cave_occluded, rendermode_cave_occluded,
rendermode_cave_hidden,
rendermode_cave_draw, rendermode_cave_draw,
}; };

View File

@@ -212,14 +212,12 @@ static inline void
do_shading_with_mask(RenderModeLighting *self, RenderState *state, do_shading_with_mask(RenderModeLighting *self, RenderState *state,
int x, int y, int z, PyObject *mask) { int x, int y, int z, PyObject *mask) {
float black_coeff; float black_coeff;
PyObject *blocks;
/* first, check for occlusion if the block is in the local chunk */ /* 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) { if (x >= 0 && x < 16 && y >= 0 && y < 16 && z >= 0 && z < 128) {
unsigned char block = getArrayByte3D(state->blocks, x, y, z); 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 */ /* this face isn't visible, so don't draw anything */
return; 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); 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 static void
rendermode_lighting_draw(void *data, RenderState *state, PyObject *src, PyObject *mask, PyObject *mask_light) { rendermode_lighting_draw(void *data, RenderState *state, PyObject *src, PyObject *mask, PyObject *mask_light) {
RenderModeLighting* self; RenderModeLighting* self;
@@ -356,5 +360,6 @@ RenderModeInterface rendermode_lighting = {
rendermode_lighting_start, rendermode_lighting_start,
rendermode_lighting_finish, rendermode_lighting_finish,
rendermode_lighting_occluded, rendermode_lighting_occluded,
rendermode_lighting_hidden,
rendermode_lighting_draw, rendermode_lighting_draw,
}; };

View File

@@ -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); 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 static void
rendermode_mineral_draw(void *data, RenderState *state, PyObject *src, PyObject *mask, PyObject *mask_light) { rendermode_mineral_draw(void *data, RenderState *state, PyObject *src, PyObject *mask, PyObject *mask_light) {
/* draw normally */ /* draw normally */
@@ -155,5 +161,6 @@ RenderModeInterface rendermode_mineral = {
rendermode_mineral_start, rendermode_mineral_start,
rendermode_mineral_finish, rendermode_mineral_finish,
rendermode_mineral_occluded, rendermode_mineral_occluded,
rendermode_mineral_hidden,
rendermode_mineral_draw, rendermode_mineral_draw,
}; };

View File

@@ -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); 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 static void
rendermode_night_draw(void *data, RenderState *state, PyObject *src, PyObject *mask, PyObject *mask_light) { rendermode_night_draw(void *data, RenderState *state, PyObject *src, PyObject *mask, PyObject *mask_light) {
/* nothing special to do */ /* nothing special to do */
@@ -67,5 +73,6 @@ RenderModeInterface rendermode_night = {
rendermode_night_start, rendermode_night_start,
rendermode_night_finish, rendermode_night_finish,
rendermode_night_occluded, rendermode_night_occluded,
rendermode_night_hidden,
rendermode_night_draw, rendermode_night_draw,
}; };

View File

@@ -135,13 +135,10 @@ rendermode_normal_finish(void *data, RenderState *state) {
static int static int
rendermode_normal_occluded(void *data, RenderState *state, int x, int y, int z) { rendermode_normal_occluded(void *data, RenderState *state, int x, int y, int z) {
RenderModeNormal *self = (RenderModeNormal *)data; if ( (x != 0) && (y != 15) && (z != 127) &&
!render_mode_hidden(state->rendermode, x-1, y, z) &&
if (z > self->max_depth || z < self->min_depth) { !render_mode_hidden(state->rendermode, x, y, z+1) &&
return 1; !render_mode_hidden(state->rendermode, x, y+1, z) &&
}
if ( (x != 0) && (y != 15) && (z != self->max_depth) &&
!is_transparent(getArrayByte3D(state->blocks, x-1, y, 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, z+1)) &&
!is_transparent(getArrayByte3D(state->blocks, x, y+1, z))) { !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; 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 static void
rendermode_normal_draw(void *data, RenderState *state, PyObject *src, PyObject *mask, PyObject *mask_light) { rendermode_normal_draw(void *data, RenderState *state, PyObject *src, PyObject *mask, PyObject *mask_light) {
RenderModeNormal *self = (RenderModeNormal *)data; RenderModeNormal *self = (RenderModeNormal *)data;
@@ -298,5 +306,6 @@ RenderModeInterface rendermode_normal = {
rendermode_normal_start, rendermode_normal_start,
rendermode_normal_finish, rendermode_normal_finish,
rendermode_normal_occluded, rendermode_normal_occluded,
rendermode_normal_hidden,
rendermode_normal_draw, rendermode_normal_draw,
}; };

View File

@@ -59,6 +59,9 @@ rendermode_overlay_finish(void *data, RenderState *state) {
static int static int
rendermode_overlay_occluded(void *data, RenderState *state, int x, int y, int z) { rendermode_overlay_occluded(void *data, RenderState *state, int x, int y, int z) {
if ( (x != 0) && (y != 15) && (z != 127) && 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-1, y, z)) &&
!is_transparent(getArrayByte3D(state->blocks, x, y, z+1)) && !is_transparent(getArrayByte3D(state->blocks, x, y, z+1)) &&
!is_transparent(getArrayByte3D(state->blocks, x, y+1, z))) { !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; 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 static void
rendermode_overlay_draw(void *data, RenderState *state, PyObject *src, PyObject *mask, PyObject *mask_light) { rendermode_overlay_draw(void *data, RenderState *state, PyObject *src, PyObject *mask, PyObject *mask_light) {
RenderModeOverlay *self = (RenderModeOverlay *)data; RenderModeOverlay *self = (RenderModeOverlay *)data;
@@ -132,5 +141,6 @@ RenderModeInterface rendermode_overlay = {
rendermode_overlay_start, rendermode_overlay_start,
rendermode_overlay_finish, rendermode_overlay_finish,
rendermode_overlay_occluded, rendermode_overlay_occluded,
rendermode_overlay_hidden,
rendermode_overlay_draw, rendermode_overlay_draw,
}; };

View File

@@ -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); 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 static void
rendermode_spawn_draw(void *data, RenderState *state, PyObject *src, PyObject *mask, PyObject *mask_light) { rendermode_spawn_draw(void *data, RenderState *state, PyObject *src, PyObject *mask, PyObject *mask_light) {
/* draw normally */ /* draw normally */
@@ -115,5 +121,6 @@ RenderModeInterface rendermode_spawn = {
rendermode_spawn_start, rendermode_spawn_start,
rendermode_spawn_finish, rendermode_spawn_finish,
rendermode_spawn_occluded, rendermode_spawn_occluded,
rendermode_spawn_hidden,
rendermode_spawn_draw, rendermode_spawn_draw,
}; };

View File

@@ -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); 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) { void render_mode_draw(RenderMode *self, PyObject *img, PyObject *mask, PyObject *mask_light) {
self->iface->draw(self->mode, self->state, img, mask, mask_light); self->iface->draw(self->mode, self->state, img, mask, mask_light);
} }

View File

@@ -62,12 +62,30 @@ struct _RenderModeInterface {
/* may return non-zero on error, last arg is options */ /* may return non-zero on error, last arg is options */
int (*start)(void *, RenderState *, PyObject *); int (*start)(void *, RenderState *, PyObject *);
void (*finish)(void *, RenderState *); 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); 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 */ /* last two arguments are img and mask, from texture lookup */
void (*draw)(void *, RenderState *, PyObject *, PyObject *, PyObject *); 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 */ /* wrapper for passing around rendermodes */
struct _RenderMode { struct _RenderMode {
void *mode; void *mode;
@@ -79,6 +97,7 @@ struct _RenderMode {
RenderMode *render_mode_create(const char *mode, RenderState *state); RenderMode *render_mode_create(const char *mode, RenderState *state);
void render_mode_destroy(RenderMode *self); void render_mode_destroy(RenderMode *self);
int render_mode_occluded(RenderMode *self, int x, int y, int z); 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); void render_mode_draw(RenderMode *self, PyObject *img, PyObject *mask, PyObject *mask_light);
/* helper function for reading in rendermode options /* helper function for reading in rendermode options