From fdadda0ea60133a5b89e37f59fcaadebe095fb1c Mon Sep 17 00:00:00 2001 From: Alejandro Aguilera Date: Sun, 19 Jun 2011 01:10:03 +0200 Subject: [PATCH] Move the average lighting coeff to another function. Take the average over blockmap. Fixes problems with stairs in night and lighting rendermode. --- src/rendermode-lighting.c | 150 +++++++++++++++++++++++++++----------- src/rendermodes.h | 2 +- 2 files changed, 107 insertions(+), 45 deletions(-) diff --git a/src/rendermode-lighting.c b/src/rendermode-lighting.c index d0d4c64..35dc688 100644 --- a/src/rendermode-lighting.c +++ b/src/rendermode-lighting.c @@ -33,21 +33,106 @@ static float calculate_darkness(unsigned char skylight, unsigned char blocklight * was calculated correctly from available light data, it will be true. You * may (and probably should) pass NULL. */ + +inline unsigned char +estimate_blocklevel(RenderModeLighting *self, RenderState *state, + int x, int y, int z, int *authoratative) { + + /* placeholders for later data arrays, coordinates */ + PyObject *blocks = NULL; + PyObject *blocklight = NULL; + int local_x = x, local_y = y, local_z = z; + unsigned char block, blocklevel; + unsigned int average_count = 0, average_gather = 0, coeff = 0; + + /* defaults to "guess" until told otherwise */ + if (authoratative) + *authoratative = 0; + + /* find out what chunk we're in, and translate accordingly */ + if (x >= 0 && y < 16) { + blocks = state->blocks; + blocklight = self->blocklight; + } else if (x < 0) { + local_x += 16; + blocks = state->left_blocks; + blocklight = self->left_blocklight; + } else if (y >= 16) { + local_y -= 16; + blocks = state->right_blocks; + blocklight = self->right_blocklight; + } + + /* make sure we have correctly-ranged coordinates */ + if (!(local_x >= 0 && local_x < 16 && + local_y >= 0 && local_y < 16 && + local_z >= 0 && local_z < 128)) { + + return 0; + } + + /* also, make sure we have enough info to correctly calculate lighting */ + if (blocks == Py_None || blocks == NULL || + blocklight == Py_None || blocklight == NULL) { + + return 0; + } + + block = getArrayByte3D(blocks, local_x, local_y, local_z); + + if (authoratative == NULL) { + int auth; + + /* iterate through all surrounding blocks to take an average */ + int dx, dy, dz, local_block; + //~ printf("\n[Starting loop]\n"); + for (dx = -1; dx <= 1; dx += 2) { + for (dy = -1; dy <= 1; dy += 2) { + for (dz = -1; dz <= 1; dz += 2) { + coeff = estimate_blocklevel(self, state, x+dx, y+dy, z+dz, &auth); + local_block = getArrayByte3D(blocks, x+dx, y+dy, z+dz); + if (auth && is_transparent(local_block)) { + average_gather += coeff; + average_count++; + } + //~ printf(" [Inside the loop] Coeff = %d, average_gather = %d, average_count = %d, auth = %d, block = %d\n", coeff, average_gather, average_count, auth, local_block); + } + } + } + } + + /* only return the average if at least one was authoratative */ + if (average_count > 0) { + int result; + float resultf; + result = average_gather / average_count; + resultf = average_gather / average_count; + //~ printf("[Outside the loop] average_gather = %d, average_count = %d\n", average_gather, average_count); + //~ printf("[Outside the loop] result = %d, resultf = %f\n", result, resultf); + return average_gather / average_count; + } + + blocklevel = getArrayByte3D(blocklight, local_x, local_y, local_z); + + /* no longer a guess */ + if (!(block == 44 || block == 53 || block == 67) && authoratative) { + *authoratative = 1; + } + + return blocklevel; +} + inline float get_lighting_coefficient(RenderModeLighting *self, RenderState *state, - int x, int y, int z, int *authoratative) { - + int x, int y, int z) { + /* placeholders for later data arrays, coordinates */ PyObject *blocks = NULL; PyObject *skylight = NULL; PyObject *blocklight = NULL; int local_x = x, local_y = y, local_z = z; unsigned char block, skylevel, blocklevel; - - /* defaults to "guess" until told otherwise */ - if (authoratative) - *authoratative = 0; - + /* find out what chunk we're in, and translate accordingly */ if (x >= 0 && y < 16) { blocks = state->blocks; @@ -64,7 +149,7 @@ get_lighting_coefficient(RenderModeLighting *self, RenderState *state, skylight = self->right_skylight; blocklight = self->right_blocklight; } - + /* make sure we have correctly-ranged coordinates */ if (!(local_x >= 0 && local_x < 16 && local_y >= 0 && local_y < 16 && @@ -72,7 +157,7 @@ get_lighting_coefficient(RenderModeLighting *self, RenderState *state, return self->calculate_darkness(15, 0); } - + /* also, make sure we have enough info to correctly calculate lighting */ if (blocks == Py_None || blocks == NULL || skylight == Py_None || skylight == NULL || @@ -89,13 +174,16 @@ get_lighting_coefficient(RenderModeLighting *self, RenderState *state, return self->calculate_darkness(15, 0); } + skylevel = getArrayByte3D(skylight, local_x, local_y, local_z); + blocklevel = getArrayByte3D(blocklight, local_x, local_y, local_z); + //~ if (block == 0 && blocklevel != 0) { + //~ printf("Para este aire tenemos skylevel %d, blocklevel %d\n", skylevel, blocklevel); + //~ } + /* 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) { - float average_gather = 0.0f; - unsigned int average_count = 0, upper_block; - int auth; - float coeff; + if (block == 44 || block == 53 || block == 67) { + unsigned int upper_block; if (local_z != 127) { /* stairs and half-blocks take the skylevel from the upper block if it's transparent */ upper_block = getArrayByte3D(blocks, local_x, local_y, local_z + 1); @@ -108,29 +196,10 @@ get_lighting_coefficient(RenderModeLighting *self, RenderState *state, skylevel = 15; blocklevel = getArrayByte3D(blocklight, local_x, local_y, local_z); } + + /* use given coordinates, no local ones! */ + blocklevel = estimate_blocklevel(self, state, x, y, z, NULL); - if (skylevel) { /* if we have a good skylevel use it, if not iterate */ - return self->calculate_darkness(skylevel, blocklevel); - } else { - - /* iterate through all surrounding blocks to take an average */ - int dx, dy, dz; - for (dx = -1; dx <= 1; dx += 2) { - for (dy = -1; dy <= 1; dy += 2) { - for (dz = -1; dz <= 1; dz += 2) { - coeff = get_lighting_coefficient(self, state, x+dx, y+dy, z+dz, &auth); - if (auth) { - average_gather += coeff; - average_count++; - } - } - } - } - - /* only return the average if at least one was authoratative */ - if (average_count > 0) - return average_gather / average_count; - } } if (block == 10 || block == 11) { @@ -138,13 +207,6 @@ get_lighting_coefficient(RenderModeLighting *self, RenderState *state, return 0.0f; } - skylevel = getArrayByte3D(skylight, local_x, local_y, local_z); - blocklevel = getArrayByte3D(blocklight, local_x, local_y, local_z); - - /* no longer a guess */ - if (authoratative) - *authoratative = 1; - return self->calculate_darkness(skylevel, blocklevel); } @@ -164,7 +226,7 @@ do_shading_with_mask(RenderModeLighting *self, RenderState *state, } } - black_coeff = get_lighting_coefficient(self, state, x, y, z, NULL); + black_coeff = get_lighting_coefficient(self, state, x, y, z); alpha_over_full(state->img, self->black_color, mask, black_coeff, state->imgx, state->imgy, 0, 0); } diff --git a/src/rendermodes.h b/src/rendermodes.h index 80126a4..bd8748a 100644 --- a/src/rendermodes.h +++ b/src/rendermodes.h @@ -118,7 +118,7 @@ typedef struct { } RenderModeLighting; extern RenderModeInterface rendermode_lighting; inline float get_lighting_coefficient(RenderModeLighting *self, RenderState *state, - int x, int y, int z, int *authoratative); + int x, int y, int z); /* NIGHT */ typedef struct {