created a distinct 'hidden' function
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -81,12 +81,68 @@ 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) {
|
||||
/* 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)) {
|
||||
@@ -170,7 +179,6 @@ 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,
|
||||
};
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user